HDD-Speedtest: Zeigt zu hohe Werte

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
saqdefaq
User
Beiträge: 3
Registriert: Dienstag 29. September 2009, 17:53

Hallo Community,

ich habe folgendes Problem: Ich habe ein kleines Programm geschrieben, mit dem die Schreibgeschwindigkeit einer Festplatte (oder USB-Stick, oder...) bei unterschiedlichen Dateigrößen getestet werden soll. Ich schreibe immer 50 MiB pro Durchgang, jeweil verteilt auf Dateigrößen von 4kiB bis zu 10 MiB. (Sollte ja auch keine Probleme mit Python geben, ist ja IO limitiert.) Die Dateien eines Durchlaufs sind auch immer exakt 50 MiB groß.
Allerdings zeigt das Programm viel zu hohe Ergebnisse und ich bin langsam mit meinem Latein am Ende.

Ich habe mittlerweile sämtliche Sachen aus den eigentlichen Schreibanteilen rausgenommen, vereinfacht, vorher die Strings generiert, welche in die Dateien sollen, etc pp.

Trotzdem erhalte ich viel zu hohe Werte - hat eventuell jemand von euch eine Idee woran es liegen könnte?

(Falls das wichtig sein sollte: Ich bin relativ neu in Python, habe jedoch einige Erfahrungen in anderen Sprachen)


Hier ist der Code:

Code: Alles auswählen

#!/usr/bin/python

import sys, os, statvfs, shutil, time

import psyco #Psyco
psyco.full()

def speedcheck(path):
        print "Ueberpruefe freien Speicher..."
        tmp = 50 * 1024 * 1024 #50mb
        
        freespace = os.statvfs(path)
        freespace = freespace[statvfs.F_BAVAIL] * freespace[statvfs.F_FRSIZE]
        
        if freespace < tmp:
                print "Nicht genug freier Speicher vorhanden"
                exit(1)
                
        print "Genug freier Speicher vorhanden (benoetigt: %d MiB)\n\nTreffe Vorbereitungen..." % (tmp / 1024 / 1024)
        #Bereite Strings vor
        str4k = ""
        str64k = ""
        str256k = ""
        str1024k = ""
        str2048k = ""
        str10m = ""
        str25m = ""
        
        for tmp in range(4 * 1024):
                str4k += "A"
                
        for tmp in range(64 * 1024):
                str64k += "A"
                
        for tmp in range(256 * 1024):
                str256k += "A"
                
        for tmp in range(1024 * 1024):
                str1024k += "A"
                
        for tmp in range(2048 * 1024):
                str2048k += "A"
                
        for tmp in range(10 * 1024 * 1024):
                str10m += "A"
                
        for tmp in range(25 * 1024 * 1024):
                str25m += "A"
                
        path = os.path.join(path, ".speedcheck")
        
        if os.path.exists(path):
                shutil.rmtree(path)
        
        os.mkdir(path)
        os.chdir(path)
        
        #4k * 12800
        print "Starte 4k Durchlauf..."
        dauer4k = time.time()
        for i in range(12800):
                file = open("4k%d" % i, "w")
                file.write(str4k)   
                file.flush()  
                file.close()

        dauer4k = time.time() - dauer4k
        
        shutil.rmtree(path)
        os.mkdir(path)
        os.chdir(path)
        
        #64k * 800
        print "Starte 64k Durchlauf..."
        dauer64k = time.time()
        for i in range(800):
                file = open("64k%d" % i, "w")
                file.write(str64k)
                file.flush()
                file.close()
                
        dauer64k = time.time() - dauer64k
        
        shutil.rmtree(path)
        os.mkdir(path)
        os.chdir(path)
                
        #256k * 200
        print "Starte 256k Durchlauf..."
        dauer256k = time.time()
        for i in range(200):
                file = open("256k%d" % i, "w")
                file.write(str256k)
                file.flush()
                file.close()
                
        dauer256k = time.time() - dauer256k
        
        shutil.rmtree(path)
        os.mkdir(path)
        os.chdir(path)
        
        #1024k * 50
        print "Starte 1024k Durchlauf..."
        dauer1024k = time.time()
        for i in range(50):
                file = open("1024k%d" % i, "w")
                file.write(str1024k)
                file.flush()
                file.close()
                
        dauer1024k = time.time() - dauer1024k
                
        shutil.rmtree(path)
        os.mkdir(path)
        os.chdir(path)
                
        #2048k * 25
        print "Starte 2048k Durchlauf..."
        dauer2048k = time.time()
        for i in range(25):
                file = open("2048k%d" % i, "w")
                file.write(str2048k)
                file.flush()
                file.close()
                
        dauer2048k = time.time() - dauer2048k
        
        shutil.rmtree(path)
        os.mkdir(path)
        os.chdir(path)
        
        #10mb * 5
        print "Starte 10m Durchlauf..."
        dauer10m = time.time()
        for i in range(5):
                file = open("10m%d" % i, "w")
                file.write(str10m)
                file.flush()
                file.close()
                
        dauer10m = time.time() - dauer10m
        
        shutil.rmtree(path)
        os.mkdir(path)
        os.chdir(path)
        
        #25mb * 2
        print "Starte 25m Durchlauf..."
        dauer25m = time.time()
        for i in range(2):
                file = open("25m%d" % i, "w")
                file.write(str25m)
                file.flush()
                file.close()
                
        dauer25m = time.time() - dauer25m
        
        print "Fertig\n\n\nErgebnisse:"
        shutil.rmtree(path)
        
        print "4k:\t\t%f MiB/s" % (50 / float(dauer4k))
        print "64k:\t\t%f MiB/s" % (50 / float(dauer64k))
        print "256k:\t\t%f MiB/s" % (50 / float(dauer256k))
        print "1024k:\t\t%f MiB/s" % (50 / float(dauer1024k))
        print "2048k:\t\t%f MiB/s" % (50 / float(dauer2048k))
        print "10m:\t\t%f MiB/s" % (50 / float(dauer10m))
        print "25m:\t\t%f MiB/s" % (50 / float(dauer25m))
        
        exit(0)
        

if len(sys.argv) > 1:
        if os.path.exists(sys.argv[1]):
                speedcheck(sys.argv[1])
        else:
                print "Pfad exisiert nicht"
else:
        print "Bitte Parameter angeben!"
        exit(0)
Als Ausgabe erhalte ich:

Code: Alles auswählen

Ueberpruefe freien Speicher...
Genug freier Speicher vorhanden (benoetigt: 50 MiB)

Treffe Vorbereitungen...
Starte 4k Durchlauf...
Starte 64k Durchlauf...
Starte 256k Durchlauf...
Starte 1024k Durchlauf...
Starte 2048k Durchlauf...
Starte 10m Durchlauf...
Starte 25m Durchlauf...
Fertig


Ergebnisse:
4k:		69.212298 MiB/s
64k:		387.657238 MiB/s
256k:		498.076713 MiB/s
1024k:		532.373421 MiB/s
2048k:		391.328330 MiB/s
10m:		421.923122 MiB/s
25m:		314.326996 MiB/s
Ausführen tu ich das unter Linux, Ubuntu 9.04 mit Python 2.6.2.
Liffi
User
Beiträge: 153
Registriert: Montag 1. Januar 2007, 17:23

ich rate mal ins Blaue hinein ohne den Code anzusehen: vielleicht liegs am Festplattencache... auch wenn das die "schlechten" Werte bei 4k nicht unbedingt erklärt.
saqdefaq
User
Beiträge: 3
Registriert: Dienstag 29. September 2009, 17:53

Ich bezweifle allerdings, ob der Cache 7*50 MiB halten kann, meine Festplatte hat afaik 16 MiB Cache.
Selbst wenn die ersten Durchläufe gecached und nach und nach auf die Platte geschrieben werden, sollte der Cache für die späteren Durchläufe doch nicht mehr ausreichen, oder?
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Das Betriebssystem hat auch Caches, das muss ja nicht alles Festplattencache sein.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
BlackJack

@saqdefaq: Wie sieht's mit anderen Faktoren wie transparente Kompression aus? Da Du nur 'A's schreibst, dürfte in dem Fall wesentlich weniger auf der Platte landen.

Die Überprüfung des freien Platteplatzes kannst Du Dir sparen. Das fällt während des Tests sowieso auf. Und genug freier Platz bedeutet nicht, dass der Benutzer den auch wirklich vollschreiben darf.

Um eine Zeichenkette mit `n` Zeichen zu erzeugen: ``'A' * n``.

Die ``exit(0)``-Aufrufe kannst Du weglassen. Ebenso das `flush()` direkt vor `close()`.

Einen Test solltest Du in eine Funktion stecken und die dann in einer Schleife für die verschiedenen Parameter aufrufen, statt Quelltext mit kopieren und einfügen zu "schreiben".
Antworten