Warum klappt Binary bei mir nicht
-
@hustbaer
leider bin ich kein so ausgefuchster Programmierer, wie Du, aber ich kann viel von Dir lernen - DANKE dafür und auch an all die anderen hier im Forum.
Ich habe jetzt erst einmal die USINGs eingebaut und die GOTOs entfernt. Braucht man bei USING keine CLOSE mehr ?
ReadAsync werde ich nun auch noch ausprobieren, ob damit noch ein paar Sekunden herauszuholen sind.//================================================= // Datei 1 und 2 lesen und vergleichen //================================================= private bool VergleicheDateien(string pDsn1, string pDsn2, Int64 lenFile, string pPfad) { bool rc = true; Int64 RestLen = lenFile; // Dateilänge beider Dateien Int64 LeseLen = Math.Min(RestLen, MaxPuffL); using (FileStream fs1 = new FileStream(pDsn1, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, FileOptions.SequentialScan)) using (FileStream fs2 = new FileStream(pDsn2, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, FileOptions.SequentialScan)) { while (LeseLen > 0 && rc) { Application.DoEvents(); if (Abbruch > 0) { return false; } GesBytes += LeseLen; // Anzahl gelesene Bytes gesamt this.Text = "CompHk " + GesBytes.ToString("###,###,###,###,##0") + " Bytes " + pPfad; fs1.Read(ByPu1, 0, (int)LeseLen); fs2.Read(ByPu2, 0, (int)LeseLen); AnzPuff++; // Anzahl verglichene Puffer if (LeseLen < 9) { for (int b = 0; b < LeseLen; b++) { if (ByPu1[b] != ByPu2[b]) { rc = false; // Es gibt Differenzen, Vergleich abbrechen } } break; } switch (VergleichsMethode) // Welche Art des Vergleiches { case compSequenceEqual: // C# interne Funktion if (!(ByPu1.Take((int)LeseLen).SequenceEqual(ByPu2.Take((int)LeseLen)))) { rc = false; // Es gibt Differenzen, Vergleich abbrechen } break; case compMemCmp: // [DllImport] msvcrt.dll if (memcmp(ByPu1, ByPu2, LeseLen) != 0) { rc = false; // Es gibt Differenzen, Vergleich abbrechen } break; case compForNxt: // C# interner Byte-für-Byte-Vergleich for (int b = 0; b < LeseLen; b++) { if (ByPu1[b] != ByPu2[b]) { rc = false; // Es gibt Differenzen, Vergleich abbrechen } } break; case compUnsafe: // unsafe MemCmp if (!MemCmp(ByPu1, ByPu2, (int)LeseLen)) { rc = false; // Es gibt Differenzen, Vergleich abbrechen } break; case compRtlCompareMemory: // [DllImport] kernel32.dll RtlCompareMemory IntPtr len = (IntPtr)LeseLen; //IntPtr rc = RtlCompareMemory(ByPu1, ByPu2, len); var rCod = RtlCompareMemory(ByPu1, ByPu2, len); if (rCod != len) { rc = false; // Es gibt Differenzen, Vergleich abbrechen } break; case compCompareByteArray: // [DllImport] CompareByteArray.dll von HK if (CompareByteArray(ByPu1, ByPu2, (int)LeseLen) != 0) { rc = false; // Es gibt Differenzen, Vergleich abbrechen } break; } // switch (VergleichsMethode) RestLen -= LeseLen; LeseLen = Math.Min(RestLen, MaxPuffL); } // while (LeseLen > 0 && rc) } if (rc) { AnzFilesOK++; } // es gibt keine Differenzen else { ByteDiff++; } // es gibt Differenzen //fs1.Close(); //fs2.Close(); return rc; } // static bool VergleicheDateien(string pDsn1, string pDsn2, Int64 lenFile)
-
@hustbaer sagte in Warum klappt Binary bei mir nicht:
var r1 = fs1.ReadAsync(ByPu1, 0, (int)LeseLen);
fs2.Read(ByPu2, 0, (int)LeseLen);
r1.Wait();var r1 = fs1.ReadAsync(ByPu1, 0, (int)LeseLen);
r1 ist m.E. doch die zurück gegebene tatsächlich gelesene Länge, also ein int-Wert.
Macht r1.Wait() dann einen Sinn ?In den gefundenen ReadAsync Beispielen sieht es etwa so aus
var r1ReadLen = await fs1.ReadAsync(ByPu1, 0, (int)LeseLen);
-
@hkdd sagte in Warum klappt Binary bei mir nicht:
Braucht man bei USING keine CLOSE mehr ?
Nein braucht man nicht dafür ist das using da, damit man nicht vergessen kann close/dispose aufzurufen.
Besonders falls eine exception geworfen wird, wird durch das using statemant definitiv immer beim verlassen des blocks close/dispose aufgerufen.
-
@hkdd sagte in Warum klappt Binary bei mir nicht:
var r1 = fs1.ReadAsync(ByPu1, 0, (int)LeseLen);
r1 ist m.E. doch die zurück gegebene tatsächlich gelesene Länge, also ein int-Wert.
Macht r1.Wait() dann einen Sinn ?In den gefundenen ReadAsync Beispielen sieht es etwa so aus
var r1ReadLen = await fs1.ReadAsync(ByPu1, 0, (int)LeseLen);
Alle asynchronen Methoden liefern ein Task (für
void
) oder Task<T>-Objekt zurück, auch Stream.ReadAsync.
Der eigentliche Rückgabewert steht dann in Result.
-
@Th69
Im Debugger habe ich mir r1 angesehen. r1.Result ist die gelesene Länge. Es gibt andere Infos. Und offenbar auch Funktionen, wie r1.Wait(), die man benutzen kann.ich habe jetzt beide Dateien mit ReadAsync gelesen und die Puffer vergrößert.
Werden die Puffer tatsächlich zeitlich parallel / gleichzeitig und nicht mehr nacheinander gelesen ?//================================================= // Datei 1 und 2 lesen und vergleichen //================================================= private bool VergleicheDateien(string pDsn1, string pDsn2, Int64 lenFile, string pPfad) { bool rc = true; Int64 RestLen = lenFile; // Dateilänge beider Dateien Int64 LeseLen = Math.Min(RestLen, MaxPuffL); using (FileStream fs1 = new FileStream(pDsn1, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, FileOptions.SequentialScan)) using (FileStream fs2 = new FileStream(pDsn2, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, FileOptions.SequentialScan)) { while (LeseLen > 0 && rc) { Application.DoEvents(); if (Abbruch > 0) { return false; } GesBytes += LeseLen; // Anzahl gelesene Bytes gesamt this.Text = "CompHk " + GesBytes.ToString("###,###,###,###,##0") + " Bytes " + pPfad; var r1 = fs1.ReadAsync(ByPu1, 0, (int)LeseLen); var r2 = fs2.ReadAsync(ByPu2, 0, (int)LeseLen); r1.Wait(); r2.Wait(); AnzPuff++; // Anzahl verglichene Puffer if (LeseLen < 9) { for (int b = 0; b < LeseLen; b++) { if (ByPu1[b] != ByPu2[b]) { rc = false; // Es gibt Differenzen, Vergleich abbrechen } } break; } switch (VergleichsMethode) // Welche Art des Vergleiches { case compSequenceEqual: // C# interne Funktion if (!(ByPu1.Take((int)LeseLen).SequenceEqual(ByPu2.Take((int)LeseLen)))) { rc = false; // Es gibt Differenzen, Vergleich abbrechen } break; case compMemCmp: // [DllImport] msvcrt.dll if (memcmp(ByPu1, ByPu2, LeseLen) != 0) { rc = false; // Es gibt Differenzen, Vergleich abbrechen } break; case compForNxt: // C# interner Byte-für-Byte-Vergleich for (int b = 0; b < LeseLen; b++) { if (ByPu1[b] != ByPu2[b]) { rc = false; // Es gibt Differenzen, Vergleich abbrechen } } break; case compUnsafe: // unsafe MemCmp if (!MemCmp(ByPu1, ByPu2, (int)LeseLen)) { rc = false; // Es gibt Differenzen, Vergleich abbrechen } break; case compRtlCompareMemory: // [DllImport] kernel32.dll RtlCompareMemory IntPtr len = (IntPtr)LeseLen; //IntPtr rc = RtlCompareMemory(ByPu1, ByPu2, len); var rCod = RtlCompareMemory(ByPu1, ByPu2, len); if (rCod != len) { rc = false; // Es gibt Differenzen, Vergleich abbrechen } break; case compCompareByteArray: // [DllImport] CompareByteArray.dll von HK if (CompareByteArray(ByPu1, ByPu2, (int)LeseLen) != 0) { rc = false; // Es gibt Differenzen, Vergleich abbrechen } break; } // switch (VergleichsMethode) RestLen -= LeseLen; LeseLen = Math.Min(RestLen, MaxPuffL); } // while (LeseLen > 0 && rc) } if (rc) { AnzFilesOK++; } // es gibt keine Differenzen else { ByteDiff++; } // es gibt Differenzen return rc; } // static bool VergleicheDateien(string pDsn1, string pDsn2, Int64 lenFile)
Hier ein paar Ergebnisse mit etwas größeren Puffern
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ CompCs - Dateien vergleichen - (C) 13.12.2022 Hartmut aus Dresden --------------------------------------------------------------- Parameter: N:\VideosN N:\VideosN --------------------------------------------------------------- Vergleich: N:\VideosN\ mit: N:\VideosN\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ============================================================ 82 Unterordner gefunden 2.446 Dateien gefunden - davon 2.446 identische Dateien verglichen. Es wurden 208.144.569.612 Bytes = 203.266.181 K-Bytes verglichen. 133.902 Puffer gelesen, Pufferlänge: 1.572.864 Bytes. Start 07:30:05 Ende 07:55:57 Dauer 00:25:52.0 ===================================================<Ende>=== ESC = Programm beenden ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ CompCs - Dateien vergleichen - (C) 14.12.2022 Hartmut aus Dresden --------------------------------------------------------------- Parameter: N:\VideosN N:\VideosN --------------------------------------------------------------- Vergleich: N:\VideosN\ MaxPuffL = 0x00180000; // Pufferlänge mit: N:\VideosN\ var r1 = fs1.ReadAsync(ByPu1, 0, (int)LeseLen); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ============================================================ 82 Unterordner gefunden 2.446 Dateien gefunden - davon 2.446 identische Dateien verglichen. Es wurden 208.144.569.612 Bytes = 203.266.181 K-Bytes verglichen. 133.902 Puffer gelesen, Pufferlänge: 1.572.864 Bytes. Start 08:24:28 Ende 08:50:29 Dauer 00:26:00.4 ===================================================<Ende>=== ESC = Programm beenden ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ CompCs - Dateien vergleichen - (C) 14.12.2022 Hartmut aus Dresden --------------------------------------------------------------- Parameter: N:\VideosN N:\VideosN --------------------------------------------------------------- Vergleich: N:\VideosN\ MaxPuffL = 0x08000000; // Pufferlänge mit: N:\VideosN\ var r1 = fs1.ReadAsync(ByPu1, 0, (int)LeseLen); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ============================================================ 82 Unterordner gefunden 2.446 Dateien gefunden - davon 2.446 identische Dateien verglichen. Es wurden 208.144.569.612 Bytes = 203.266.181 K-Bytes verglichen. 3.424 Puffer gelesen, Pufferlänge: 134.217.728 Bytes. Start 08:51:59 Ende 09:19:00 Dauer 00:27:00.9 ===================================================<Ende>=== ESC = Programm beenden ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ CompCs - Dateien vergleichen - (C) 14.12.2022 Hartmut aus Dresden --------------------------------------------------------------- Parameter: N:\VideosN N:\VideosN --------------------------------------------------------------- Vergleich: N:\VideosN\ MaxPuffL = 0x00800000; // Pufferlänge mit: N:\VideosN\ fs1 und fs2 ReadAsync ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ============================================================ 82 Unterordner gefunden 2.446 Dateien gefunden - davon 2.446 identische Dateien verglichen. Es wurden 208.144.569.612 Bytes = 203.266.181 K-Bytes verglichen. 26.474 Puffer gelesen, Pufferlänge: 8.388.608 Bytes. Start 09:23:35 Ende 09:48:57 Dauer 00:25:21.5 ===================================================<Ende>=== ESC = Programm beenden ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
Werden die Puffer tatsächlich zeitlich parallel / gleichzeitig und nicht mehr nacheinander gelesen ?
Ja. Dazu reicht es allerdings wenn man einen der beiden Reads (den ersten) "async" macht. Das erste
ReadAsync
startet dabei das Lesen des Blocks aus dem 1. File. Daneben läuft das Programm weiter und kann den 2. Read synchron machen. Wenn der 2. Read fertig ist, muss man noch warten dass der erste, asynchrone auch fertig ist - könnte ja sein dass der 2. Read aus irgend einem Grund schneller war. Das macht dasr1.Wait()
.Bringt aber nichts, wenn du 2x vom selben Laufwerk liest. Weil Zugriffe auf das selbe Laufwerk werden nicht schneller, nur weil man 2 parallel macht. Es könnte die Sache sogar erheblich langsamer machen. Wenn es allerdings verschiedene Laufwerke sind, dann bringt es u.U. viel, denn dann können beide Laufwerke gleichzeitig lesen.
Kann, muss aber nicht, weil das OS evtl. "read ahead" macht. Ob das passiert und wie gut es funktioniert hängt von einigen Faktoren ab. U.a. der OS Version und der Puffergrösse. (Read ahead wird nur bis zu einer maximalen Puffergrösse gemacht.)
Aktuell scheinst du mit 2x dem selben Verzeichnis zu testen. Das macht mMn. eher wenig Sinn wenn du Performance-Tests machen willst. Wenn du das Programm auf den Einsatz mit 2 verschiedenen Laufwerken optimieren willst, dann solltest du auch mit 2 verschiedenen Laufwerken testen. Bzw. wenn du das Programm auf den Einsatz mit 2 Verzeichnissen auf dem selben Laufwerk optimieren willst, dann solltest du auch mit 2 verschiedenen Verzeichnissen auf dem selben Laufwerk testen. Und wenn du möglichst gute Performance in beiden Fällen haben willst, dann solltest du auch beide testen
So wie du es jetzt machst, also 2x das selbe Verzeichnis lesen, wird halt effektiv nur 1x wirklich vom Laufwerk gelesen. Beim 2. mal Lesen kommen die Daten dann aus dem File Cache - weil's ja das selbe File ist.
-
@hustbaer sagte in Warum klappt Binary bei mir nicht:
weil's ja das selbe File ist
Danke für Deine Erläuterungen. Das ist mir schon klar und in der Anwendung will ich ja damit gesicherte Daten vergleichen, die stehen dann auf einer externen HDD oder evtl. sogar auf eine DVD / Blueray oder einem USB-Stick oder einem Netzlaufwerk.
Weil das Delphi-Programm so deutlich schneller war, wollte ich den Overhead von C# ermitteln, also alles, was mit dem Lesen und auch dem Vergleichen gar nichts zu tun hat, nur der Grundaufwand für das Lesen der Directorys usw.
Deshalb habe ich ja auch Test-Schalter, mit denen ich das Einlesen und Vergleichen überspringen kann.
Das habe ich inzwischen ganz gut hinbekommen, so dass der Unterschied zum Delphi-Programm kaum noch erkennbar ist.
Solche weiteren Optimierungen, wie asynchrones / zeilich paralleles Lesen gibt es bei Delphi 7 nicht. Die neueren Delphi-Versionen können das sicherlich auch.
-
@hustbaer sagte in Warum klappt Binary bei mir nicht:
dann solltest du auch mit 2 verschiedenen Laufwerken testen
Das habe ich jetzt gemacht
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ CompHKw - Dateien Vergleichen - (C) 12.12.2022 Hartmut aus Dresden DELPHI Lauf 1 ----------------------------------------------------------------------------------------------------------- Parameter: "V:\#Musik\#MP3-aus-WAV\#TB-MP3" "Z:\#Musik\#MP3-aus-WAV\#TB-MP3" "/U" "/VN" "/F" "/M:200" "/A" ----------------------------------------------------------------------------------------------------------- Vergleich: V:\#Musik\#MP3-aus-WAV\#TB-MP3\ DELPHI Lauf 1 mit: Z:\#Musik\#MP3-aus-WAV\#TB-MP3\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4.880.Datei: V:\#Musik\#MP3-aus-WAV...ger\72-gs-638 Lang Lang ist´s her [Heino].mp3 ================================================================= 246 Unter-Pfade gefunden - identisch. 4.880 Dateien gefunden - und verglichen... 4.880 Dateien verglichen - identisch. Es wurden 25.148.066.175 Bytes = 24.558.658 K-Bytes verglichen Start 18:30:05 Ende 18:34:55 Dauer 00:04:50 ========================================================<Ende>=== Linke MausTaste / ESC = Schließen Rechte MausTaste / F1 = Info ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ CompHKw - Dateien Vergleichen - (C) 12.12.2022 Hartmut aus Dresden DELPHI Lauf 2 ----------------------------------------------------------------------------------------------------------- Parameter: "V:\#Musik\#MP3-aus-WAV\#TB-MP3" "Z:\#Musik\#MP3-aus-WAV\#TB-MP3" "/U" "/VN" "/F" "/M:200" "/A" ----------------------------------------------------------------------------------------------------------- Vergleich: V:\#Musik\#MP3-aus-WAV\#TB-MP3\ mit: Z:\#Musik\#MP3-aus-WAV\#TB-MP3\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4.880.Datei: V:\#Musik\#MP3-aus-WAV...ger\72-gs-638 Lang Lang ist´s her [Heino].mp3 ================================================================= 246 Unter-Pfade gefunden - identisch. 4.880 Dateien gefunden - und verglichen... 4.880 Dateien verglichen - identisch. Es wurden 25.148.066.175 Bytes = 24.558.658 K-Bytes verglichen Start 18:37:00 Ende 18:42:18 Dauer 00:05:18 ========================================================<Ende>=== Linke MausTaste / ESC = Schließen Rechte MausTaste / F1 = Info ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ CompCs - Dateien vergleichen - (C) 14.12.2022 Hartmut aus Dresden C# Lauf1 --------------------------------------------------------------- Parameter: V:\#Musik\#MP3-aus-WAV\#TB-MP3 Z:\#Musik\#MP3-aus-WAV\#TB-MP3 --------------------------------------------------------------- Vergleich: V:\#Musik\#MP3-aus-WAV\#TB-MP3\ mit: Z:\#Musik\#MP3-aus-WAV\#TB-MP3\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ============================================================ 246 Unterordner gefunden 4.880 Dateien gefunden - davon 4.880 identische Dateien verglichen. Es wurden 25.148.066.175 Bytes = 24.558.658 K-Bytes verglichen. 18.447 Puffer gelesen, Pufferlänge: 1.572.864 Bytes. Start 18:43:06 Ende 18:44:52 Dauer 00:01:45.6 ===================================================<Ende>=== ESC = Programm beenden ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ CompCs - Dateien vergleichen - (C) 14.12.2022 Hartmut aus Dresden C# Lauf2 --------------------------------------------------------------- Parameter: V:\#Musik\#MP3-aus-WAV\#TB-MP3 Z:\#Musik\#MP3-aus-WAV\#TB-MP3 --------------------------------------------------------------- Vergleich: V:\#Musik\#MP3-aus-WAV\#TB-MP3\ mit: Z:\#Musik\#MP3-aus-WAV\#TB-MP3\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ============================================================ 246 Unterordner gefunden 4.880 Dateien gefunden - davon 4.880 identische Dateien verglichen. Es wurden 25.148.066.175 Bytes = 24.558.658 K-Bytes verglichen. 18.447 Puffer gelesen, Pufferlänge: 1.572.864 Bytes. Start 18:45:35 Ende 18:49:15 Dauer 00:03:39.7 statt 9:15 bei C# ALT ===================================================<Ende>=== ESC = Programm beenden ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Die Delphi-Version braucht etwa 5 Minuten, die neue C#-Version 2 bis 3 Minuten und meine alte C# Version über 9 Minuten.
Es werden mp3-Dateien auf einer internen sATA3-HDD mit einer USB3-Sicherungs-HDD verglichen.
-
@hkdd
D.h. das Ding ist jetzt nicht nur gleich schnell, sondern schneller. NiceNoch ein Tip: wenn's um's Lesen von Files geht, spielt ja der File-Cache immer mit rein. Dadurch bekommst du dann unterschiedliche Zeiten je nachdem ob du mit warmem oder kaltem Cache testest. Wenn du nicht für jeden Test den PC rebooten willst, kannst du mit USB HDDs testen. In deinem Fall bräuchtest du halt 2 USB HDDs. Wenn du die vor jedem Test ab- und wieder ansteckst hast du wieder kalte Caches.
-
@hustbaer sagte in Warum klappt Binary bei mir nicht:
spielt ja der File-Cache immer mit rei
Das habe ich mir ja auch gedacht, deshalb habe ich jeweils zweimal das Programm laufen lassen.
Beim Delphi-Programm war der zweite Lauf schneller (warmer Cache).
Beim C# Programm war er allerdings langsamer, als der erste ( überhitzter Cache ??? )