Android 用の視覚化アプリを開発しています (Android 2.2 を実行している古いデバイスを含む)。
私のアプリの入力モデルには、通常、数万の頂点で構成される領域が含まれています。典型的なモデルは 50000 から 100000 の頂点 (それぞれx、y、z 座標 float
を持つ) を持ちます。つまり、600K から 1200 キロバイトの合計メモリを消費します。アプリでは、すべての頂点がいつでもメモリ内で使用できる必要があります。このアプリについて共有できるのはこれだけです (高レベルの使用例を共有することは許可されていません)。そのため、以下の結論が正しいかどうか、およびより良い解決策があるかどうか疑問に思っています。
たとえば、count
=50000 個の頂点があるとします。2 つの解決策があります。
1.) 私の以前の解決策は、独自のものを使用していましたVertexObj
(カプセル化による読みやすさの向上、個々の座標にアクセスする際の局所性の向上):
public static class VertexObj {
public float x, y, z;
}
VertexObj mVertices = new VertexObj[count]; // 50,000 objects
2.) 私の他のアイデアは、float[]
代わりに大きなものを使用することです:
float[] mVertices = new VertexObj[count * 3]; // 150,000 float values
最初の解決策の問題は、大きなメモリ オーバーヘッドです。アプリのヒープが 16 ~ 24 MB に制限されている可能性があるモバイル デバイスを使用しています (そして、私のアプリは他のことにもメモリを必要とします)。Androidの公式ページによると、本当に必要でない場合はオブジェクトの割り当てを避ける必要があります。この場合、頂点が 50,000 であってもメモリ オーバーヘッドは非常に大きくなる可能性があります。
まず第一に、「有用な」メモリは 50000*3*4 = 600K です (これは値によって使い果たされfloat
ます)。次に、要素のために +200K のオーバーヘッドがVertexObj
あり、おそらく Java オブジェクト ヘッダーのためにさらに +400K のオーバーヘッドがあります (Android でもオブジェクトごとに少なくとも 8 バイトです)。これは、50,000 個の頂点に対して 600K の「無駄な」メモリであり、100% のオーバーヘッド (!) です。100,000 頂点の場合、オーバーヘッドは 1.2MB です。
2 番目のソリューションは、値に有効な 600K のみを必要とするため、はるかに優れていfloat
ます。
どうやら結論としては で行くべきfloat[]
なのですが、この場合のリスクを知りたいです。私の疑問は、メモリ管理の低レベル (厳密には Android 固有ではない) の側面にも関連している可能性があることに注意してください。
私が知る限り、私が書くnew float[300000]
と、アプリは VM に 300000*4 = 1200K バイトの連続ブロックを予約するように要求します。( Dalvik ヒープに 1MB をはるかに超える空き領域がbyte[]
あるにもかかわらず、 Android で 1MB を要求したところ、 が返されました。これは、1MB の連続したブロックを予約できなかったためだと思います。)OutOfMemoryException
Android の VM の GC は圧縮 GC ではないため、メモリが「フラグメント化」されている場合、そのような膨大なfloat[]
割り当てが OOM を引き起こす可能性があるのではないかと心配しています。私がここにいるなら、このリスクは処理されるべきです。たとえば、より多くのオブジェクトを割り当てるのはどうfloat[]
でしょうか (それぞれが 200KB などの部分を格納します)。このようなリンク リスト メモリ管理メカニズムは、オペレーティング システムと VM で使用されるため、ここ (アプリケーション レベル) で使用する必要があるとは思えません。私は何が欠けていますか?
何もない場合、最善の解決策はオブジェクトのリンクリストを使用することだと思いfloat[]
ます(OOMを回避し、オーバーヘッドを小さく保つため)?