none
Kuriosität bei Lese und Schreibzugriff auf USB-Laufwerk RRS feed

  • Frage

  • Hallo,

    Ich hoffe, dass mir hier jemand den entscheidenden Tipp geben kann.

    Anbei ein Programmausschnitt, der Schreibgeschwindigkeit, Lesegeschwindigkeit und Fehler auf einem Laufwerk finden soll.

    Das Problem ist: das beschreiben funktioniert einwandfrei. Schreibgeschwindigkeit stimmt.

    Das lesen funktioniert aber nicht richtig, will heißen, geht viel zu schnell. Nur wenn ich das Programm beende und beim nächsten Mal nur lese stimmt die Lesegeschwindigkeit. Das Programm stellt hier also irgendeinen Zusammenhang zwischen dem Lese und Schreibarry her. Das kuriose ist, selbst, wenn das geschriebene Array auf dem Datenträger nicht mit dem zu schreibenden Array übereinstimmt (weil Sektoren Kaput sind) liest das Programm das richtige Array ein (bzw. speichert das Richtige Array im Lesepuffer)

    Hier findet wohl irgendeine ungewollte Codeoptimierung statt! Kann mir jemand sagen wie ich das lösen kann? Bzw. hat irgendwer eine Idee? (Ich brauche nicht erwähnen, dass ich schon gefühlt alles ausprobiert habe)

    Module Module1
        Public Function LaufwerkPruefen(Pfad As String) As Boolean
    
            Dim Startzeit As Date
            Dim Schreibgeschwindigkeit, Lesegeschwindigkeit As Double
            Dim Dateigrösse As Double = 1024 * 1024 * 50 '50MB
            Dim SchreibBytes(Dateigrösse) As Byte 'Bytes die geschrieben werden sollen
            Dim LeseBytes(Dateigrösse) As Byte 'Bytes die gelesen werden sollen
    
            'Mit zufallszahlen füllen um es dem USB-Stick schwieriger zu machen
            Dim R As New System.Random
            R.NextBytes(SchreibBytes)
    
            'Beschreiben
            Startzeit = Now
            My.Computer.FileSystem.WriteAllBytes(Pfad & "\test" & ".ABC", SchreibBytes, False)
            Schreibgeschwindigkeit = Dateigrösse / (1024 ^ 2) / (CInt(System.DateTime.Now.Subtract(Startzeit).TotalMilliseconds)) * 1000
    
            'Lesen
            Startzeit = Now
            LeseBytes = IO.File.ReadAllBytes(Pfad & "\test" & ".ABC")
            Lesegeschwindigkeit = Dateigrösse / (1024 ^ 2) / (CInt(System.DateTime.Now.Subtract(Startzeit).TotalMilliseconds)) * 1000
    
            'Prüfen
            For i As Integer = 0 To SchreibBytes.Length - 1
                If Not (SchreibBytes(i) = LeseBytes(i)) Then
                    ' Byte-Element sind unterschiedlich!
                    Return False
    
                End If
            Next
    
            Return True
    
        End Function
    End Module

    Dienstag, 4. Juni 2013 12:50

Antworten

  • Hallo,

    mit High-Level Routinen wie sie von .NET verwendet werden, kann man die Performance nicht realistisch messen. Da beeinflussen u. a. die Windows Caches Messergebnisse zu stark.

    Schau Dir mal an: http://www.heise.de/download/h2testw.html

    Gruß Elmar

    Dienstag, 4. Juni 2013 14:12
    Beantworter
  • Hallo,

    fehlerhafte Sektoren kannst Du so schon mal gar nicht erkennen. Erkennt Windows, dass ein Zugriff aus dem Cache erfolgen kann, so greift es erst gar nicht auf den USB Stick zu.

    Um ein direktes Schreiben zu erzwingen müsste man die FileOption.WriteThrough verwenden.

    Funktionieren kann das bestenfalls, wenn Du den USB Stick einmal auswirfst, damit der Cache als ungültig erklärt wird. Auch dann können Dinge wie das Verlagern von defekten Sektoren das Ergebnis verfälschen.

    Wirklich zuverlässige Ergebnisse gibt es nur, wenn man den Cache umgeht, aber auch Treiber Einstellungen können es beeinflussen - so sind - wurde mal in der C't behandelt - diverse Sticks zu finden, die bei der Kapazität lügen.

    Das geht aber nur mit Low-Level Zugriffen (und hier auch technischen Kenntnisse über den Aufbau von USB Sticks). Dies kann man in .NET alleine jedoch nicht programmieren.

    Gruß Elmar

    Dienstag, 4. Juni 2013 14:59
    Beantworter

Alle Antworten

  • Hallo,

    ich denke mal das da die Code-Optimierung dazwischen geht. Das geht ggf. in den Projekteigenschaften unter Kompilieren > Erweiterte Kompilierungsoptionen zu deaktivieren.

    Ich habe deinen Code nur ohne Optimierung getestet. Da gab es keine Zeitlich-Großen unterschiede.

    PS: Gehe bitte vom My-Namnespace weg. Zum Schreiben/Lesen von Dateien nutze bitte die entsprechenden Streams oder die File-Klasse.

    PPS: Zum Zeit stoppen: http://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch.aspx


    <Code:13/> - Koopakiller [kuːpakɪllɐ]
    Webseite | Code Beispiele | Facebook | Snippets
    Wenn die Frage beantwortet ist, dann markiert die hilfreichsten Beiträge als Antwort und bewertet die Beiträge. Danke.
    Einen Konverter zwischen C# und VB.NET Code gibt es hier.

    Dienstag, 4. Juni 2013 13:10
    Moderator
  • Danke schon mal für den TIPP

    -          Projekt->[Name] Eigenschaften->Kompilieren->Erweiterte Kompilierungsoptionen-> Optimierung aktivieren  ist nicht gesetzt, da ich das auch schon vermutet hatte!

    -          Stopwatch ist wahrscheinlich wirklich besser aber, das ist leider nicht das Problem. Dennoch ein guter Tipp

    Die 50 Mb sind natürlich nur für einen sehr langsamen USB Stick (ca. 1,7 Mb/s) d.h. bei einem schnelleren, sollte man eventuell ein Größeres Array definieren, um das Problem erfassen zu können.

    Dienstag, 4. Juni 2013 13:31
  • Hallo,

    mit High-Level Routinen wie sie von .NET verwendet werden, kann man die Performance nicht realistisch messen. Da beeinflussen u. a. die Windows Caches Messergebnisse zu stark.

    Schau Dir mal an: http://www.heise.de/download/h2testw.html

    Gruß Elmar

    Dienstag, 4. Juni 2013 14:12
    Beantworter
  • Hallo das Tool ist mir bekannt! Hilft mir aber nicht!

    Mich interessiert gar nicht wirklich die Schreibgeschwindigkeit als vielmehr fehlerhafte Sektoren! Diese werden aber auch nicht erkannt, da das zweite Array mit den Daten befüllt wird die logischerweise drin seien müssten und nicht denen, die bei fehlerhaften Sektoren wirklich drin sind!

    Das Programm sagt immer Schreibbytes = Lesebytes selbst wenn dem nicht so ist! Weil es ja eigentlich so seinen sollte.

    Dienstag, 4. Juni 2013 14:27
  • Hallo,

    fehlerhafte Sektoren kannst Du so schon mal gar nicht erkennen. Erkennt Windows, dass ein Zugriff aus dem Cache erfolgen kann, so greift es erst gar nicht auf den USB Stick zu.

    Um ein direktes Schreiben zu erzwingen müsste man die FileOption.WriteThrough verwenden.

    Funktionieren kann das bestenfalls, wenn Du den USB Stick einmal auswirfst, damit der Cache als ungültig erklärt wird. Auch dann können Dinge wie das Verlagern von defekten Sektoren das Ergebnis verfälschen.

    Wirklich zuverlässige Ergebnisse gibt es nur, wenn man den Cache umgeht, aber auch Treiber Einstellungen können es beeinflussen - so sind - wurde mal in der C't behandelt - diverse Sticks zu finden, die bei der Kapazität lügen.

    Das geht aber nur mit Low-Level Zugriffen (und hier auch technischen Kenntnisse über den Aufbau von USB Sticks). Dies kann man in .NET alleine jedoch nicht programmieren.

    Gruß Elmar

    Dienstag, 4. Juni 2013 14:59
    Beantworter