8

ときどき、特にアプリに新しい機能を実装するときは、DDMS + HPROF を使用してメモリとヒープの使用状況を分析します。アプリにはパフォーマンス - ANR の問題はないようで、すべてがスムーズに機能するため、最初は気にしませんでしたが、今ではほぼ常に同じサイズであることがわかり、何ができるのか疑問に思っています。なれ。

HPROF を実行するたびに、 [リークの疑い] タブをチェックします。android.graphics.Bitmap使用されているすべてのヒープの約 25% を占めるインスタンスが常に存在します。

リーク容疑者

それが何であるかをもう少し知りたかったので、ドミネーターツリーを開いて、これを見ました:

ドミネーターツリー

したがって、本質的にbyte[]、大量のヒープを保持し、決して解放されない巨大なインスタンスがあります。thisによると、 that の値をコピーしbyte[]てファイルにダンプし.data、Gimp で開いたところ、次の結果が得られました。

PNG

つまり、基本的には PNG 画像の「alpha(0)」の部分のように見えます。次の事実を考慮してください。

  • すべての画像ファイルのサイズは 8K 未満です
  • そのうちのいくつかは PNG ですが、残りは JPG に変換できました。
  • さらに画像を追加しても問題ありませんが、そのサイズはbyte[]アプリの開始時 (4 か月前) からほぼ同じです。
  • それをデバッグするために、フォルダーとフォルダーから画像ファイルを削除し、描画可能なリソースなしでアプリを実行しようとしました、まだそこにありましたdrawabledrawable-xxxbyte[]
  • ほとんどすべてのレイアウトを削除し、基本的な機能だけを残しましたが、結果は同じでした
  • ドミネーター ツリーでは、ルート クラスはandroid.graphics.Bitmap

誰でもこれが何であるかを知っていbyte[]ますか?それを解放するために何かをする必要がありますか?

どんな助けでも大歓迎です!

4

1 に答える 1

8

いくつかのことを明確にするために:

  • アプリ内の画像/ドローアブルは、メモリ内で の形式で使用されますandroid.graphics.Bitmap
  • Android 3.0 (API レベル 11) 以降、ピクセル データは関連するビットマップと共に Dalvik ヒープに保存されます。(ビットマップメモリ​​の管理)
  • 「huge byte[]」は、1MB を超えるヒープ スペースであるため、おそらく誇張されています。

Leak Suspectsレポートは役に立つ場合がありますが、この場合、その最大の容疑者が 1MB を超えるメモリであることを考えると、あまり情報が得られません。最新のデバイスは 64MB 以上のヒープを提供しています。

このビットマップのメモリ要件を計算してみましょう。このビットマップは、ヒープで 1,127,584 バイトを占めています。このビットマップが ARGB_8888 を使用して構成されていると仮定すると、各ピクセルは 4 バイトを使用します。つまり、画像には 281,896 ピクセル (または約 530x530) が含まれることになります。これはあなたがしていることに対して不合理に聞こえますか?

また、mdpi、hdpi、xhdpi などのドローアブルのさまざまな「バケット」間で Android がスケーリングする方法を検討してください。mdpi バケットに 200x200 の画像がありxhdpiデバイスでアプリを開いているとします。この画像は 2 倍の大きさにスケーリングされ、デバイス上の解像度は 400x400 になります。そのため、200x200 の画像は多くのヒープ領域 (200 x 200 x 4 = 160 kb ) を必要としないかもしれませんが、400x400 の画像には比較的大きな量 (4x) のヒープ領域 (400 x 400 x 4 = 640 kb ) が必要になります。詳細については、複数画面のサポートを参照してください。

画像バケットとの違いをすばやく計算するための優れたツール: Android DPI Calculator

ドローアブルの一部を削除したとおっしゃいましたが、何が残っていますか? 外部ライブラリから来る可能性のあるドローアブルを考慮しましたか?

最後の質問に答えるには:このバイト [] が何なのか、それを解放するために何かする必要があるかどうかは誰でも知っていますか?

私はこう言います:ヒープ上のこの少量のメモリは心配する必要はありません。それが気になる場合は、目を離さず、実用的と思われる範囲を超えて成長していないことを確認してください。それでもメモリ リークが疑われる場合は、画面間を移動し、ヒープが拡大し続けるかどうかを確認します。ビットマップをキャッシュしていないと仮定すると、ヒープは、2 つの画面間を行き来するときに一貫した/予測可能なサイズを維持する必要があります。

補足として、DDMS を使用すると、その場でヒープ サイズを非常に簡単に監視できます。飛び込む準備が整うまで、HPROF ダンプは必要ありません。Using DDMS を参照してください。初期ヒープサイズの更新をトリガーするために必要になるため、「Cause GC」ボタンに特に注意してください。

--更新--

これにさらに答えるために、私が持っているサポートされていない疑いの 1 つは、アプリのアセット (システム アセット/テクスチャ?) の一部がアプリのメモリ空間に読み込まれているということです。こちらのスライド 64 をご覧ください: Android 4.4 の新機能

Android 4.4 では、すべてのプロセスで共有される、すべてのフレームワーク アセットを含む単一のテクスチャが生成されるようになりました。これにより、すべてのプロセスでメモリが少し節約されますが、描画操作をバッチ処理およびマージしてアプリケーションを自動的に最適化するのにも役立ちます。

これは、4.4 より前のバージョンを実行している各アプリのシステム ビットマップ/ドローアブルにメモリが使用されていることを示しているようです。この場合、この1MBがそのスペースであるかどうか疑問に思います. アプリを 4.4 デバイス/エミュレーターで実行して、同じメモリが使用されているかどうかを確認していただけないでしょうか。

別のテストとして、ベアボーン アプリのメモリ使用量を調べてみましたか (すべてのドローアブルを削除するなど)。

于 2014-01-29T08:40:58.880 に答える