web-dev-qa-db-ja.com

カーソルウィンドウ:ウィンドウがいっぱいです

クエリから返されたデータが入力されたListViewを作成しました。
動作しますが、LogCatに次のメッセージが表示されます。

Cursor Window: Window is full: requested allocation 444 bytes, free space 363 bytes, window size 2097152 bytes

そして、ListViewのロード/視覚化に数分を使用します。

私のクエリは、String/Int/Doubleの約3700行を返します。各行には30列があります。画像や特定のデータ型はありません

このメッセージはどういう意味ですか、どうすれば回避できますか?
このカーソルウィンドウを変更してパフォーマンスを改善できますか?

31
Tirrel

私の経験から、これはクエリ結果がカーソルのウィンドウに対して大きすぎ、より多くのメモリを要求することを意味します。ほとんどの場合、このリクエストは受け入れられますが、ローエンドデバイスでは例外がスローされる可能性があります。

問題のアプリの詳細はわかりませんが、ListViewを参照しました。 ListViewは一度に3700行を表示できず、 endless list はオンデマンドでデータをロードするのに役立ちます

私のアドバイスは、クエリを複数のクエリに分割してより小さな結果を返し、次のクエリを実行する前にそれらを閉じることです。連続する各クエリの後、結果を結合します。

16
Delblanco

ショートバージョン:

調査の結果、このメッセージは通常の操作の一部であり、懸念の原因ではないようです。それは「警告」レベルで記録されますが、これは単に熱心すぎると思います。

長いバージョン:

これは(明確にラベルが付けられた)「ウィンドウ付き」カーソルです。つまり、新しいレコードが取得されると、古いレコードは破棄されます。最も単純な形式では、このような「ウィンドウ」実装には、合計N行まで含めることができます。ただし、この実装では、ウィンドウサイズは合計サイズによって定義されます。代わりに、メモリに保持される行数は、ウィンドウ全体に収まる行数に基づいており、実行時に変化します(これは、「ウィンドウ化された」カーソルよりも「バッファリングされた」カーソルと考えることができます)。

(ソフト?)キャップされたサイズのバッファー付き実装として、最初の行は、次の行を収容するにはバッファーがいっぱいである場合にのみ破棄されます。この場合、1つ以上の古い行が削除されます。この「行を割り当てるスペースを確保できなくなるまで、必要に応じて行を割り当ててください。その時点で、バッファー内の最も古いレコードを解放して再試行する」プロセスは、通常の部分として完全に正常で予期されているようですメモリ空間を制限するためのプロセスの。

この結論は、ここでソースを読むことといくつかの推論を組み合わせたものに基づいています: https://Android.googlesource.com/platform/frameworks/base/+/master/libs/androidfw/CursorWindow.cpp

なぜ人々は画像やその他の大規模なLOBについて話しているのですか?

単一の行のサイズが「ウィンドウ」(バッファ)全体より大きい場合、この戦略は失敗し、実際に問題が発生します。

これは、@ opが受け取っていたメッセージです。

Cursor Window: Window is full: requested allocation 444 bytes, free space 363 bytes, window size 2097152 bytes

これは、@ vovahostが受け取っていたメッセージです。

CursorWindow: Window is full: requested allocation 2202504 bytes, free space 2076560 bytes, window size 2097152 bytes

最初のケースでは、要求された割り当てはウィンドウサイズよりもはるかに小さくなります。同じウィンドウサイズで、リクエストされた割り当てサイズを変えて、同様のメッセージが繰り返し発行されることを期待しています。これが印刷されるたびに、メモリは大きなウィンドウから解放され、新しい割り当てが行われます。これは正常で正常な動作です。

2番目のケースでは、要求された割り当てサイズがウィンドウ全体のサイズを超えています。これは実際の問題であり、よりストリーミング可能な方法でデータを格納および読み取る必要があります。

違いは、「長さ」(行の総数)対「幅」(最大の単一行のメモリコスト)です。前者(@tirrelの問題)は問題ではありませんが、後者(@vovahostの問題)は問題です。

5
user1575326

私もこの問題を抱えています。私の場合、2.2 MBの画像をデータベースに保存しました。 Cursor.getBlob()を使用してデータベースからデータをロードすると、ログに次のメッセージが表示されます。

CursorWindow: Window is full: requested allocation 2202504 bytes, free space 2076560 bytes, window size 2097152 bytes

後続の行のデータ(文字列、数値など)を取得しようとすると、このメッセージが表示された後、エラーなくnullとして返されます。解決策は、2.2 MBのブロブを削除することでした。 Androidのデータベースから大きなblobをロードできるかどうかはわかりません。

3
vovahost