2

ruby、python、scala をテストして、どれが巨大な配列をより適切にサポートしているかを確認していました。

Ruby (each) -> 84 MB, 2s # a = [];(0...1e7).each{|i| a[i]=i}
Ruby (expand) -> 254 MB, 60s #a = [*(0...1e7)]
Python (numpy) -> 95 MB, < 1s # a = np.arange(0, 1e7)
Python (range) -> 391 MB, < 1s # a = list(range(0, int(1e7)))
Scala (range) -> Memory Limit Exceeded :-) # var a = Range(0, 1e7.toInt).map(_.toInt)

ご覧のとおり、scala を使用するとメモリ制限を超えます。何が問題なのですか?!!!

--UPDATE

わかりました、私は使うべきでした

var a = Array.range(0, 1e7.toInt)

しかし、配列を文字列にマップしたい場合はどうすればよいでしょうか?

var b = a.map(_.toString())

ここで失敗…

4

3 に答える 3

4

Scala の Range は、純粋な意味で配列と同じではありません (内部では N 個の項目を保持するだけでなく、いくつかの追加の作業を行っているため、メモリ効率が低下し、メモリをより速く消費します)。

Array.range(0, 1e7.toInt)python の np.arange に近くなり、正常に動作します。

于 2013-04-25T08:58:06.200 に答える
3

典型的な長さ 7 の 1,000 万の文字列が必要で (1,000 万の整数もあります)、JVM の文字列は 1 文字あたり 2 バイト (およびオーバーヘッド) であるため、これを保持するには少なくとも 180 MB が必要です。それが実際にどれほど悪いかを見てみましょう。

$ scala -J-Xmx896M -e 'println(Array.range(0,1e7.toInt).map(_.toString).apply(9999999))'
9999999

$ scala -J-Xmx832M -e 'println(Array.range(0,1e7.toInt).map(_.toString).apply(9999999))'
java.lang.OutOfMemoryError: Java heap space

では、どうぞ。予想の約 4.5 倍悪い。JVM はこの種のことはあまり得意ではありません。各文字列は実際には 2 つのオブジェクト (文字列と文字配列) であり、オブジェクトには約 12 バイトのオーバーヘッドとコンテンツがあり、適切な境界に切り上げられます。また、JVM 自体を実行するには、いくらかのスペースが必要です (そして、特にインタープリターを含む Scala で読み込まれるすべてのクラスについて)。だからこれは「合理的」です。

ただし、ここでは巨大な配列のサポートをテストしていません。Java のメモリ効率をテストしていますStringが、あまり効率的ではありません。

于 2013-04-25T11:18:23.413 に答える