2012-03-29 2 views
0

私はAndroidにやや複雑なゲームエンジンを作成しています。Android:スレッドを更新するとGCがトンを実行します

現在サブシステムの更新にスレッドが使用されています。

更新方法の中には、現在のゲーム状態に基づいてゲームロジックを更新する方法があります。

ゲームの状態にはシーンが更新されています。シーンはルートノードで構成され、単純なシーングラフ構造になります。

ルーツは、更新された子を持つノードなどです。

Logcat:03-29 09:23:22.866:D/dalvikvm(18554):GC_CONCURRENTは511K、52%無料で無料になるまで、これは何とか素晴らしいものです。 2773K/5767K、外部77K/587K、一時停止2ms + 3ms

サブシステムを更新する方法をコメントアウトするときに、GCメッセージがないので、更新ループになる原因を切り離しました。さらに、私は更新ループについて深くコメントしています。ルートノードの子プロセスが更新される時点までは、GCが精力的に実行される時点までです。

(GameLgoic) 
public void onUpdate(float deltaTime) 
    { 
     if (gameState != null) 
      gameState.onUpdate(deltaTime); 
    } 
(GameState) 
public void onUpdate(float deltaTime) 
    { 
     scene.onUpdate(deltaTime); 
    } 
(Scene) 
public void onUpdate(float deltaTime) 
    { 
     root.onUpdate(deltaTime); 
    } 
(SceneNode) 
public void onUpdate(float deltaTime) 
    { 
     for (int i = 0; i < children.size(); ++i) 
     { 
      children.get(i).onUpdate(deltaTime); // Memory leak runs crazily here 
     } 
    } 

私がコメントしているのはchildren.get(i).onUpdate(deltaTime)リークはありません!私の心はとてもうんざりです。みんなありがとう。

+1

グッドニュースを:あなたのリークにonUpdate()の呼び出しではありません。そのメソッドの内部にあるコードです。関連するコードスニペットを追加してください。 – WarrenFaith

+1

'children'の定義と関連する' onUpdate'メソッドを示してください。 – Gray

+2

ああ、ループで 'size()'を呼び出すたびに、子猫が死ぬ。 – WarrenFaith

答えて

2

私はAndroid用ゲームを作ったときに同様の問題に遭遇しました。これを回避する唯一の方法は、埋め込みCスタイルをコード化することです。あなたはループをしたい場合 だから、そのようなあなたのカウント変数、だけでなく、あなたの境界変数を、可能な限り、再利用:

int i; 
int max 
void loop(){ 
    max = bla.size(); 
    for(i=0; i<max; i++){ ... } 
} 

同じことは、あなたが触れる他の文字通りすべてのために行きます。したがって、不要になったオブジェクトへの参照を保持し、後でそれらをリサイクルすることを検討することもできます。

これらの変更を実装することは、ゲームにどのような違いをもたらしたのかは狂っています。 Framerateは倍増し、遅延の大幅な削減などが可能です。

あなたはEclipse SDKであるdelieverdであるDDMSツールを調べてください。これらの問題を回避するために、割り当てを追跡するために使用することができます。

さらに、ループにジャンプしてリサイクルできなくなるたびに割り当てられるため、すべてのインターレーターを削除することを検討する必要があります。したがって、手作業でループし、長い回でガベージコレクタを待たなければならないよりも、リストを複数回(ループ内でget(x))歩く方が良いです。

+0

の後にあなたの提案をチェックしてみてください。しかし、彼が '私がchildren.get(i).onUpdate(deltaTime)をコメントアウトすると、漏れはありません!ループ自体ではなく... – WarrenFaith

+0

この場合、for(子c:子)構文も便利です。 – Jave

+0

私はちょうどそれをカバーするために私の答えを拡張しました。イテレータはGCによって収集されるオブジェクトでもありますので、残念なことにオプションはありません。 – devsnd

0

最初に用語を明確にする - にはa memory leakがあります。メモリリークは、もはや使用していないメモリを解放していないために、アプリケーションのメモリ使用量が増え、増加したときに発生します。 とは逆にの問題があります。使用していないメモリがたくさんありますが、それはgarbage collectedでなければなりません。

通常、使用されていないメモリを解放することは良いことです。リリースされたメモリをクリーンアップするために必要なガベージコレクションが、ここで見ているパフォーマンスの問題を引き起こす場合にのみ問題になります。

これまでに投稿したコードに大きな問題はありません。その問題は、onUpdate()メソッドの中にあるので、そのコードを投稿することができます。

一般に、可能であればオブジェクトを破棄して作成するのではなく、オブジェクトを再利用してガベージコレクションを削減することができます。最後に

、マイナーポイント、あなたは置き換えることができます。

for (int i = 0; i < children.size(); ++i) 
{ 
    children.get(i).onUpdate(deltaTime); // Memory leak runs crazily here 
} 

a for loopで:

for (SomeClass child : children) { 
    child.onUpdate(deltaTime); 
} 
+0

病気に少しそれを与える!ありがとう。 – DubyaDubyaDubyaDot

関連する問題