6

メモリ内で一度に処理するには大きすぎる約 600 万行を返すクエリがあります。

各クエリは Tuple3[String, Int, java.sql.Timestamp] を返します。文字列が約 20 文字 (UTF8) を超えることはありません。

これらのタプルの 1 つの最大サイズを計算するにはどうすればよいですか? また、より一般的には、このような scala データ構造のサイズを概算するにはどうすればよいでしょうか?

私が使用しているマシンには6Gbがあります。ただし、データは scala-query を使用してデータベースから scala のリストに読み込まれています。

4

2 に答える 2

6

Scala オブジェクトは Java オブジェクトとほぼ同じ規則に従うため、それらに関する情報は正確です。 ここに 1 つのソースがありますが、これは少なくとも 32 ビット JVM にほとんど適しているようです。(64 ビット JVM はポインターごとに 8 バイトを使用します。これは通常、4 バイトの余分なオーバーヘッドにポインターごとに 4 バイトを加えたものになります。しかし、JVM が圧縮ポインターを使用している場合は、それが少なくなる可能性があります。現在はデフォルトで使用されていると思います。)

圧縮ポインターのない 64 ビット マシンを想定します (最悪の場合)。次に、aTuple3には 2 つのポインター (16 バイト) とInt(4 バイト) とオブジェクト オーバーヘッド (~12 バイト) があり、最も近い 8 または 32 バイトに丸められます。のInt。(悲しいことに、タプルでプリミティブを使用すると、ラップされたバージョンを使用する場合よりもさらに多くのスペースが必要になります。) String32 バイト、IIRC に、1 文字あたり 16 プラス 2 のデータの配列を加えたものです。 java.sql.Timestampいくつかの s を保存する必要があるためLong(そうだと思います)、32 バイトになります。全体として、120 バイトと 1 文字あたり 2 バイトのオーダーであり、20 文字で 160 バイトになります。

または、オブジェクトのサイズを直接測定する方法については、この回答を参照してください。この方法で測定すると、160 バイトになります (上記の見積もりは、このデータを使用して修正されているため一致します。以前はいくつかの小さなエラーがありました)。

于 2012-06-26T14:22:28.947 に答える
2

自由に使えるメモリはどれくらいありますか?トリプルの600万インスタンスは実際にはそれほど多くありません!

各参照には、32ビットまたは64ビットのどちらを実行しているかに応じて4バイトまたは8バイトのオーバーヘッドがあります(これは、32Gb未満のヒープのJDK7のデフォルトですが、圧縮された「oops」はありません)。

したがって、トリプルには3つの参照があり(特殊化のために余分な参照がある場合があります。したがって、4つの参照を取得する可能性があります)、 (8バイト)Timestampのラッパー(参照)です。longあなたIntは専門化されます(つまり、基礎となるint)ので、これはさらに4バイトになります。文字列は20x2バイトです。したがって、基本的に、 1行あたり100バイトをはるかに下回る最悪のケースがあります。つまり、kbあたり10行、Mbあたり10,000行です。したがって、1Gb未満のヒープで600万行を快適に処理できます。

率直に言って、このスペースで毎日数百万行の約20フィールド(小数、文字列などを含む)を快適に処理しているため、ここで間違いを犯したと思います。

于 2012-06-26T14:15:19.050 に答える