2012-03-28 8 views
1

Ich habe 4 Dictionarys, die 800k Strings mit 200 bis 6000 Zeichen enthalten. Wenn ich es in den Speicher laden, dauert es etwa 11 GB Speicher. dauert es 2 Minuten, um die Daten zu analysieren und 2 Minuten, um die Daten auszugeben. gibt es sowieso, um die Daten schneller als das, was ich unten verwende, auszugeben? Ich erhalte nur 20-31 MB pro Sekunde Disk IO und ich weiß, dass die Festplatte 800ish tun könnenAusgabe Wörterbuch optimal

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

Auf einen Blick führen Sie doppelt so viele Hash-Lookups wie erforderlich. Verwenden Sie stattdessen 'Dictionary.TryGetValue'. Wenn das Ergebnis falsch ist, wissen Sie, dass es nicht existiert. Wenn es wahr zurückgibt, haben Sie bereits Ihren Wert. Als Kommentar hinterlassen, weil ich keine Zeit habe, das Problem auf einer höheren Ebene zu analysieren. Auch .... 'using' Blöcke sind dein Freund. Was passiert, wenn einer dieser Aufrufe von 'Write' eine Ausnahme auslöst? Sie werden nicht nach Ihren Streams so schnell aufräumen, wie Sie möchten. –

+1

Dies ist möglicherweise eine bessere Frage für [code review] (http://codereview.stackexchange.com), da Sie nicht wirklich auf ein Problem stoßen. –

+0

Was ist 'mswithfilenames'? – Tigran

Antwort

2

Der teuerste Teil ist die I/O. Und diese Schleife:

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]); 
    } 
    ... 
} 

ist im Wechsel zwischen verschiedenen Dateien. Das verursacht wahrscheinlich zusätzliche Kopfbewegungen und erzeugt fragmentierte Dateien (verlangsamt zukünftige Aktionen für diese Dateien).

Ich würde verwenden:

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]); 
    } 
} 
... 

Aber natürlich sollte man diese messen. Auf SSDs wird es zum Beispiel nur auf mechanischen Festplatten keinen großen Unterschied machen.

+0

danke, ich bin auf einer mechanischen Festplatte und ich werde die Leistung in wenigen Augenblicken überprüfen –

+0

danke, dass die Laufzeit um 27% zu reduzieren! –

1

Können Sie ein Dictionary<int, Dictionary<string, myCustomDataHolder>> statt vier separate, parallele Dictionary<int, Dictionary<string, string> haben? Es sollte nicht nur der Platzbedarf erheblich reduziert werden, sondern auch 1/4 der Dictionary-Lookups.

Es ist nicht ganz klar, ob die Wörterbücher bei Ihrer Frage völlig parallel sind, aber es scheint mir wahrscheinlich genug zu sein.

+0

die Informationen in jedem der Dictionarys ist einzigartig zu diesem Hash ich weiß nicht wirklich, wie ich sie zusammenführen könnte –

+0

Sie verwenden den Dateinamen als Schlüssel in allen Wörterbüchern , fügen Sie einfach einen 'index1' 'index2' usw. an jeden an. Wenn Sie diese Wörterbücher im gleichen Manuskript auffüllen, verwenden Sie einfach den einfachen Dateinamen als Schlüssel, ohne 'index1' anzuhängen usw. Wenn die Daten bereits 'index1' angehängt haben, können Sie sie entfernen? – Servy

+0

lassen Sie mich für ein paar Minuten darüber nachdenken, dass scheint, als ob ich einen Fehler machen würde, wenn ich es tun wollte haha ​​:) –

3

Haben Sie etwas gemessen? Es hört sich an, als ob Sie nicht triviale Datenmenge zum Lesen und Schreiben haben - der erste Schritt wäre also, eine absolute Basis für Ihr Festplattensubsystem festzulegen, wie schnell es so viele Daten liest/schreibt. Einfaches Lesen der Datei gefolgt von Schreiben in die neue Datei mit der ungefähren Datenmenge, die Sie erwarten, zeigt, wie weit Sie bei der Optimierung gehen können.

Es kann sein, dass Ihr Code selbst nicht viel mehr Zeit zum Lesen/Schreiben braucht.

+1

ja Ich habe die Zeiten gemessen und einfach kopieren und Einfügen der Dateien von einem Ordner zu einem anderen dauert etwa 3 Sekunden (2.5gigs mit der Festplatte, die ich bei 855meg/s habe). Ich möchte die Schrift auch so schnell aus dem Gedächtnis holen. –

0

würde Ich mag, dass greift

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

Takes 2 Hash-Tabelle hinzuzufügen. Eine für den Schlüssel contains und eine für den eigentlichen Zugriff. Viele Wörterbuchzugriffe können sich addieren, so dass Sie diese Zugriffe mit dem Wörterbuch tryGetValue-Methode halbieren können. Dies wird diese beiden Aufrufe zu einem kombinieren. Ich könnte erklären, wie das funktioniert, aber das macht den Job besser als ich: http://www.dotnetperls.com/trygetvalue