12

この質問には、パフォーマンス上の理由からJavaでのメモリ管理が含まれます。このプログラムをAndroidゲームとして開発しており、メモリGCによってパフォーマンスが低下するためです。そのため、これまでに多くの作業を行っており、ゲームのメモリ使用量を最適化するという素晴らしい仕事をしていることがわかりましたが、問題が1つあります。それはイテレータです。

これが私がしていることです:

  1. ゲームレベルを開始します。
  2. 割り当てトラッカーを開始します(この方法では、レベルが実行されている限り残るすべての割り当てを無視します。レベルの最初に1回だけ作成されるオブジェクトが多数あり、問題はありません)。
  3. レベルでいくつかのことを行い、割り当てを取得します。

私の割り当てはこれでいっぱいです:

466 24 java.util.AbstractList $ SimpleListIterator 12 java.util.AbstractList iterator
465 24 java.util.AbstractList $ SimpleListIterator 12 java.util.AbstractList iterator
464 24 java.util.AbstractList $ SimpleListIterator 12 java.util.AbstractList iterator
463 24 java.util.AbstractList $ SimpleListIterator 12 java.util.AbstractList iterator
461 24 java.util.AbstractList $ SimpleListIterator 12 java.util.AbstractList iterator
456 24 java.util.ArrayList $ ArrayListIterator 12 java.util.ArrayList iterator
45424java。 util.ArrayList $ ArrayListIterator 12 java.util.ArrayList iterator
453 24 java.util.ArrayList $ ArrayListIterator 12 java.util.ArrayList iterator
452 24 java.util.ArrayList $ ArrayListIterator 12 java.util.ArrayList iterator

したがって、ゲームの実行中に割り当てられるオブジェクトはイテレータだけです。さて、それを修正するために...私が尋ねた問題を引き起こしているコードは何ですか...ここにあります:

for (Segment side : listOfSides.getSides()) {
    // do stuff
}

はい、for-each構文は、各要素にデータを入力するために舞台裏でイテレータを呼び出します。これは完全に理にかなっており、私が期待していたこととまったく同じですが、それがそれほどひどく蓄積され、ゲームのパフォーマンスの問題を引き起こす可能性があることに気づいていませんでした。この問題を取り除くことができれば、どの電話を使用していても、ゲームは本当に稲妻のように動作します。だから私の質問は、これらの一時的なイテレータのすべてが作成されてすぐに破棄されて厄介なGCの実行が発生しないようにするにはどうすればよいですか?私のコードを完全に醜くしない方法でそうすることのボーナスポイント!(Androidでndkを使用することはできません)

PSすべてのArrayListについて、get(int i)関数を使用し始めることができると考えていました。これらは舞台裏の配列であり、ヒープではなくスタックに配置されるインデックスに使用する整数です。しかし、HashMapやLinkedListのような他のオブジェクトについては、何をすべきかわかりません。

4

3 に答える 3

14

ArrayListとLinkedListを使用すると、get(int i)を使用して要素をトラバースできます(LinkedListの場合は遅くなる可能性があり、get()の実装方法がわかりません)。これは、イテレーターの割り当てを回避するための推奨アプローチです。プラットフォームのソースコードを見ると、for-each構文の使用をできるだけ避けようとしていることがわかります。

HashMapの場合、entrySet()を使用して基になるセットを取得し、toArray(Object [])を呼び出して、すべての値を保持するのに十分な大きさの事前に割り当てられた配列を渡すことができます。または、Androidが提供するさまざまなSparseArrayクラスを使用できるかどうかを確認してください。

于 2012-07-15T07:41:31.527 に答える
1

設定した制約を考えると、唯一の解決策は、インデックス付けと、ArrayListまたは配列のいずれかを使用することです。そして、のためLinkedListHashMap、私は割り当てを回避する実用的な代替手段はないと思います。

しかし、GCは本当に遅いので、このようにマイクロ最適化の極限に進む必要がありますか?

于 2012-07-15T07:40:36.447 に答える
0

foreachループは、リストで使用するときに常にイテレータを取得します。メモリを割り当てないようにする方法は2つだけです。どちらもコードを醜くする必要があります。

  • リストの代わりに生の配列で使用します(最も簡単なアプローチ)。

  • iterator()関数がメモリを割り当てないListまたは他のIterableで使用します。これは一種のハードコアになり、おそらくそれだけの価値はありませんが、私が本当にループを最適化したい場合にそれを行いました。これが私がそれをした方法です:

    1. Iterableを実装する独自のコンテナクラスを作成します。(foreachループは、Listのサブクラスでなくても、Iterableを実装するすべてのもので機能します。)
    2. iterator()関数を介してイテレータを返すときにメモリを割り当てないように、そのクラスを作成します。これを行うには、イテレータのプールを用意し、イテレータを取得してその値をリセットします。コードの中には、同じコレクションを反復処理する複数のネストされたループが含まれている可能性があるため、単一のプールを再利用するのではなく、プールが必要になる可能性があります。
    3. 上記の醜いソリューションのデバッグに数時間を費やしてください。全体として、ほとんどの場合、それだけの価値はありません。
于 2012-07-16T03:35:40.573 に答える