Ich muss große Dateien auf einigen Computern synchronisieren. Die Dateien können bis zu 6 GB groß sein. Die Synchronisierung erfolgt alle paar Wochen manuell. Ich kann den Dateinamen nicht berücksichtigen, da sie sich jederzeit ändern können.
Mein Plan ist es, Prüfsummen auf dem Ziel-PC und auf dem Quell-PC zu erstellen und dann alle Dateien mit einer Prüfsumme, die sich noch nicht im Ziel befinden, auf das Ziel zu kopieren. Mein erster Versuch war ungefähr so:
using System.IO;
using System.Security.Cryptography;
private static string GetChecksum(string file)
{
using (FileStream stream = File.OpenRead(file))
{
SHA256Managed sha = new SHA256Managed();
byte[] checksum = sha.ComputeHash(stream);
return BitConverter.ToString(checksum).Replace("-", String.Empty);
}
}
Das Problem war die Laufzeit:
- mit SHA256 mit einer 1,6-GB-Datei -> 20 Minuten
- mit MD5 mit einer 1,6-GB-Datei -> 6,15 Minuten
Gibt es einen besseren - schnelleren - Weg, um die Prüfsumme zu erhalten (möglicherweise mit einer besseren Hash-Funktion)?
c#
.net
large-files
checksum
Crono
quelle
quelle
Antworten:
Das Problem hierbei ist, dass jeweils
SHA256Managed
4096 Bytes gelesen werden (erben vonFileStream
und überschreiben, umRead(byte[], int, int)
zu sehen, wie viel vom Dateistream gelesen wird), was ein zu kleiner Puffer für Festplatten-E / A ist.Um Dinge zu beschleunigen (2 Minuten für Hashing 2 GB - Datei auf meinem Rechner mit SHA256, 1 Minute für MD5) Wrap
FileStream
inBufferedStream
und setzt in üblichen Größe Puffergröße (Ich habe versucht , mit ~ 1 Mb - Puffer):quelle
Prüfen Sie nicht die gesamte Datei, sondern erstellen Sie etwa alle 100 MB Prüfsummen, damit jede Datei eine Sammlung von Prüfsummen enthält.
Wenn Sie dann Prüfsummen vergleichen, können Sie den Vergleich nach der ersten anderen Prüfsumme beenden, frühzeitig aussteigen und sich die Verarbeitung der gesamten Datei ersparen.
Für identische Dateien dauert es immer noch die volle Zeit.
quelle
Wie Anton Gogolev feststellte , liest FileStream standardmäßig jeweils 4096 Byte. Sie können jedoch mit dem FileStream-Konstruktor jeden anderen Wert angeben:
Beachten Sie, dass Brad Abrams von Microsoft im Jahr 2004 schrieb:
Quelle
quelle
Rufen Sie den Windows-Port von md5sum.exe auf . Es ist ungefähr doppelt so schnell wie die .NET-Implementierung (zumindest auf meinem Computer mit einer 1,2-GB-Datei).
quelle
Ok - danke an euch alle - lasst mich das zusammenfassen:
quelle
Ich habe Tests mit Puffergröße durchgeführt und diesen Code ausgeführt
Und ich habe mit einer Datei von 29½ GB Größe getestet, die Ergebnisse waren
Ich verwende eine i5 2500K-CPU, 12 GB RAM und ein OCZ Vertex 4 256 GB SSD-Laufwerk.
Also dachte ich mir, was ist mit einer Standard-2-TB-Festplatte? Und die Ergebnisse waren so
Daher würde ich entweder keinen Puffer oder einen Puffer von maximal 1 Mühle empfehlen.
quelle
Sie machen etwas falsch (wahrscheinlich zu kleiner Lesepuffer). Auf einer Maschine im unalterten Alter (Athlon 2x1800MP von 2002), auf der DMA auf der Festplatte wahrscheinlich aus dem Ruder gelaufen ist (6,6 M / s sind verdammt langsam, wenn sequentielle Lesevorgänge ausgeführt werden):
Erstellen Sie eine 1G-Datei mit "zufälligen" Daten:
1m5.299s
1m58.832s
Das ist auch komisch, md5 ist für mich durchweg langsamer als sha1 (mehrmals wiederholen).
quelle
Ich weiß, dass ich zu spät zur Party komme, aber einen Test durchgeführt habe, bevor ich die Lösung tatsächlich implementiert habe.
Ich habe einen Test gegen die eingebaute MD5-Klasse und auch gegen md5sum.exe durchgeführt . In meinem Fall dauerte die eingebaute Klasse 13 Sekunden, wobei md5sum.exe bei jedem Lauf ebenfalls etwa 16 bis 18 Sekunden dauerte.
quelle
Sie können einen Blick auf XxHash.Net werfen ( https://github.com/wilhelmliao/xxHash.NET ).
Der xxHash-Algorithmus scheint schneller zu sein als alle anderen.
Einige Benchmarks auf der xxHash-Website: https://github.com/Cyan4973/xxHash
PS: Ich habe es noch nicht benutzt.
quelle