2016-04-26 12 views
0

Goはかなり新しく、私はメモリ使用量を理解するのにいくつかの問題を抱えています。[]文字列のメモリ使用量を減らすには?

csvに似たファイルを行の配列にロードしたいのですが、各行は22文字のキーと、値の配列(文字列)
私のコードは次のようになります:https://play.golang.org/p/hJ4SHjVXaG

問題は、450Mのファイルでは約2G1のメモリを使用しています。
メモリ使用量を削減するソリューションはありますか? SirDarius溶液を用い

更新:https://play.golang.org/p/DBmOFOkZdxはまだ1G9

+0

あなたのプログラムではどのような問題を解決できますか?メモリ削減技術は、問題の種類によって大きく異なる場合があります。 – rootatdarkstar

+0

ファイルを1行ずつ読み込みます。レシピはこちら:http://stackoverflow.com/a/8758113/1975086 –

+1

一度にすべてをメモリに保存しておきますか? @AlexanderTrakhimenokが示唆しているようにファイルを行単位で処理できませんか? – icza

答えて

6

ファイルにはいくつの行とフィールドがありますか?

説明していることは、最小限のメモリを使用している可能性があります。

コードを見ると、基礎となる文字列データには450MBのメモリが使用されると思います。

これをスライスして文字列にします。これらは、64ビットプラットフォーム上で16バイトを取るポインタと長さで構成されています。

だから1.5GB/16 = 93Million。

あなたのファイルに50万以上のフィールドがある場合、メモリの使用は妥当と思われます。

これは正確な計算ではないので、行数などの他のオーバーヘッドがあります。

EDIT


5万行、800メガバイトを取る16のバイト5000万列ヘッダである10カラム各

を考えます。さらにデータそのもの450MB、5 * 8 * 500万行= 200MBの場合1.45GB

完全なメモリ割り当てでも1.5GB以下の使用量を減らすことはできません。

+1

5万行、10列の各 – rWick

2

の周りに使用するには、これは私にはかなり非効率です:あなたは、基本的にそのスライス上で、ループをstring.Split関数を呼び出すことによって[]stringを取得し、

for _, value := range strings.Split(line[23:], ";") { 
    row.Values = append(row.Values, value) 
} 

すべての文字列を別の文字列スライスに追加します。

理由だけでない。代わりに

row.Values = strings.Split(line[23:], ";") 

私はそれを保証することはできませんが、ループによって各文字列がコピーされる可能性があります。そのため、必要に応じてプログラムが2倍のメモリを使用する可能性があります。

+0

確かに、それはかなり役に立たない、私はそのループでいくつかの妥当性チェックがあったが、私はそれらを延期することができます。 私はちょうど試みたが、それは1g9、完璧ではないが、すでに、より良いに取り掛かります!ありがとう! – rWick

1

巨大なファイルサイズが妥当な方法ではないことを考慮して、各繰り返しで得られた値を構造体に追加しています。なぜあなたはバッチでファイルを処理していないのですか?

Split関数を見ると、部分文字列のスライスが返されるため、結果のスライスを範囲指定してrow.Valuesに追加する必要はありません。結果の値を直接row.Valuesに割り当ててから、rowsスライスに追加することができます。 9月で区切られたすべてのサブストリングに

func Split(s, sep string) []string 

分割スライスSおよびそれらの間のセパレータサブストリングの スライスを返します。 sepが空の場合、 分割は各UTF-8シーケンスの後で分割されます。これは、SplitN と-1のカウントを持つことに相当します。

row.Values = strings.Split(line[23:], ";") 
rows = append(rows, row) 
0

それはおよそ()関数を追加します私には思えます。言語仕様

Sの容量は追加の値をフィットするのに十分な大きさでない場合より、 APPENDはこの新しく割り当てられた配列の

サイズは十分に十分であることができる新しい、十分に大きな根本的な配列を割り当てより多くの追加を消費する。したがって、正確に割り当てるにはslice := make([]Row, 0, WithExpectedCapacity)を指定し、ではなくslice[n]=を割り当てます。あなたがこれを行うことができない場合は、少なくとも反射が

reflect.ValueOf(&slice).Elem().SetCap(len(slice)) 

いくつかのトリッキーを圧縮しようとすることができますが、それが動作https://play.golang.org/p/LslkOBCvIIを見ることができます。

+0

は、私は私のテストのために使用するファイルのサイズを知っているので、私は手動で各アレイの容量を設定しようとしたが、大した結果と... は、だから私はそれはないだろうと思います私は追加を使用していなかったので、多くの変更が、私は試してみましょう! – rWick

関連する問題