2012-03-28 13 views
1

私は200kから6000文字の800kの文字列を含む4つの辞書を持っています。 メモリにロードすると、約11ギガバイトのメモリが必要になります。 データを解析するのに2分、データを出力するのに2分かかります。 私が以下で使用しているものより速くデータを出力するには、とにかくありますか? 私は第二のディスクIOあたり20〜31メガバイトを取得していますし、私は、ハードドライブが800ish最適に出力する辞書

var hash1 = new Dictionary<int, Dictionary<string, string>>(f.Count + 2); 
var hash2 = new Dictionary<int, Dictionary<string, string>>(f.Count + 2); 
var hash3 = new Dictionary<int, Dictionary<string, string>>(f.Count + 2); 
var hash4 = new Dictionary<int, Dictionary<string, string>>(f.Count + 2); 
.... 
foreach (var me in mswithfilenames) 
{ 
    filename = me.Key.ToString(); 
    string filenamef = filename + "index1"; 
    string filenameq = filename + "index2"; 
    string filenamefq = filename + "index3"; 
    string filenameqq = filename + "index4"; 

    StreamWriter sw = File.AppendText(filenamef); 
    StreamWriter sw2 = File.AppendText(filenameq); 
    StreamWriter swq = File.AppendText(filenamefq); 
    StreamWriter sw2q = File.AppendText(filenameqq); 

    for (i = 0; i <= totalinhash; i++) 
    { 
     if (hashs1[i].ContainsKey(filenamef)) 
     { 
      sw.Write(hashs1[i][filenamef]); 
     } 
     if (hashs2[i].ContainsKey(filenameq)) 
     { 
      sw2.Write(hashs2[i][filenameq]); 
     } 
     if (hashs3[i].ContainsKey(filenamefastaq)) 
     { 
      swq.Write(hash4[i][filenamefastaq]); 
     } 

     if (hash4[i].ContainsKey(filenameqq)) 
     { 
      sw2q.Write(hash4[i][filenameqq]); 
     } 
    } 

    sw.Close(); 
    sw2.Close(); 
    sw3.Close(); 
    sw4.Close(); 
    swq.Close(); 
    sw2q.Close(); 
} 
+6

一見、必要な数のハッシュ検索を2回実行しています。代わりに 'Dictionary.TryGetValue'を使用してください。それが偽を返す場合、それが存在しないことを知っています、それが真を返すなら、あなたは既にあなたの価値を持っています。私は問題をより高いレベルで分析する時間がないので、コメントとして残しておきます。また.... 'using'ブロックはあなたの友人です。 'Write'への呼び出しのどれかが例外をスローするとどうなりますか?あなたはあなたのストリームの後にあなたが好きなだけ素早くクリーンアップすることはありません。 –

+1

実際に問題に遭遇していないので、[コードレビュー](http://codereview.stackexchange.com)の方がより良い質問になるかもしれません。 –

+0

'mswithfilenames'とは何ですか? – Tigran

答えて

2

最も高価な部分はI/Oです。そして、このループ:

for (i = 0; i <= totalinhash; i++) 
{ 
    if (hashs1[i].ContainsKey(filenamef)) 
    { 
     sw.Write(hashs1[i][filenamef]); 
    } 
    if (hashs2[i].ContainsKey(filenameq)) 
    { 
     sw2.Write(hashs2[i][filenameq]); 
    } 
    ... 
} 

は、異なるファイル間で交互に表示されます。おそらく頭部の動きが増え、断片化したファイルが作成されます(これらのファイルの将来の動作が遅くなります)。

私が使用します。

for (i = 0; i <= totalinhash; i++) 
{ 
    if (hashs1[i].ContainsKey(filenamef)) 
    { 
     sw.Write(hashs1[i][filenamef]); 
    } 
} 

for (i = 0; i <= totalinhash; i++) 
{ 
    if (hashs2[i].ContainsKey(filenameq)) 
    { 
     sw2.Write(hashs2[i][filenameq]); 
    } 
} 
... 

しかし、もちろん、あなたがこれを測定する必要があります。たとえば、SSDは機械的なディスクだけで大きな違いはありません。

+0

私は機械的なディスクの上にいるので、私は少しの時間でパフォーマンスをチェックします –

+0

27%のカットランタイムに感謝! –

1

を行うことができますがDictionary<int, Dictionary<string, myCustomDataHolder>>ではなく、4つの別々の並列Dictionary<int, Dictionary<string, string>を持つことができます知っていますか?それは消費されるスペースを大幅に削減するだけでなく、辞書のルックアップの1/4を意味します。

あなたの質問があれば、辞書が完全に並行しているかどうかは明らかではありませんが、私にとってはそうであるようです。

+0

各辞書の情報はそのハッシュに固有のものです。私はそれらをマージする方法を本当に知りません –

+0

すべての辞書のキーとしてファイル名を使用しています、それぞれに 'index1'、 'index2'などを追加するだけです。これらの辞書を同じマナーに入れている場合は、 'index1'などを追加せずにキーとしてプレーンファイル名を使用します。データに既に 'index1'が追加されている場合は削除できますか? – Servy

+0

私はそれがハハをやろうとするとバグを作り出すかもしれないような数分は考えてみましょう:) –

3

何か測定しましたか?読んだり書いたりするデータ量が少なくて済むように思えます。そのため、ディスクサブシステムのデータの読み書き速度の絶対基準を確立することが第一歩です。ファイルの単純な読み込みに続いて、予想されるおおよその量の新しいファイルへの書き込みが、最適化にどれだけ近づけることができるかを示します。

コード自体の読み書きに時間がかかりすぎても問題ありません。

+1

はい私は時間を測定し、単純に1つのフォルダから別のフォルダにファイルをコピーして貼り付けるのに約3秒かかった(私は855meg/sのハードドライブで2.5ギガバイト)。私はメモリからの書き込みも速くしたいと思います。 –

0

私は

if (hashs1[i].ContainsKey(filenamef)) 
{ 
    sw.Write(hashs1[i][filenamef]); 
} 

がアクセス2ハッシュテーブルを取ることを追加したいと思います。 1つはcontainsキー用で、もう1つは実際のアクセス用です。多くの辞書アクセスが追加される可能性があるため、辞書tryGetValueメソッドを使用してこれらのアクセスを半分にすることができます。これにより、これら2つのコールが1つに統合されます。私はこれがどのように動作するか説明できますが、これは私よりもうまく機能します:http://www.dotnetperls.com/trygetvalue

関連する問題