PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Strategie gesucht: Datei in mehrere Teile splitten


Gast
2012-01-08, 01:53:41
Hallo!

Wie im Titel zu lesen ist, möchte ich gerne programmatisch eine Datei in mehrere Teile splitten und suche eine gute Vorgehensweise. Was ich damit meine?

Nun, ich könnte zunächst die gesamte Datei einlesen und dann (evt. mutlithreaded) mit dem Splitten beginnen. Ich könnte aber auch einen Block lesen, dann speichern und wieder von vorne (wobei man das Speichern wieder in einen Thread auslagern könnte, so dass sofort weitergelesen werden kann).

Gesucht wird die schnellste Variante. Allerdings geht es hier ja nicht nur um CPU-Load, sondern auch um Schreib-/Lesezugriffe auf die Platte, und da habe ich null Erfahrung bisher. Ich glaube, dass könnte eher der Flaschenhals sein. Man müsste also wissen, wie man reads und writes am Besten aufteilt oder aneinander vorbei bekommt, denke ich mir zumindest.

Genutzt wird übrigens .NET.


Danke

Monger
2012-01-08, 02:49:33
Festplatte ist definitiv der Flaschenhals. Was dann konkret das schnellste Verfahren ist, hängt auch stark von der Größe und Zahl der zu verarbeitenden Dateien ab: wenige, kleine Dateien sind wahrscheinlich vorallem durch die Zugriffszeit limitiert. Wieviele Zugriffe parallel auf die selbe Festplatte gemacht werden können, könnte stark von der Festplatte abhängen.

Wie eigentlich immer, erste Regel: Don't optimize (yet)

Zweite Regel: Performance Messungen grundsätzlich nur am lebenden Objekt (d.h. am gesamten Programm in einem realen Use-Case), sonst bekommst du keine belastbaren Ergebnisse.

Ich empfehle dir, nimm einen Threadpool mit einer fixen Zahl an Threads, und probier einfach mal verschieden viele Einstellungen (beginnend bei einem Thread) aus.

BAGZZlash
2012-01-08, 10:01:17
Eigentlich ist es doch klar: Du solltest möglichst lange Burstreads und -writes durchführen.
Es gibt zwei Grenzbereiche:


Ein Byte lesen, ein Byte schreiben, ein Byte lesen...
Viele Bytes lesen, dann viele Bytes schreiben, ggf. wieder viele Bytes lesen...

Das Extrem zu Punkt zwei wäre, die Quelldatei zunächst komplett einzulesen und dann in Häppchen hintereinander wegzuschreiben. Dies sollte die schnellste Methode sein, denn bei Festplatten bremst vor allem die Zugriffszeit, die bei sequenziellen Zugriffen aber entfällt bzw. zumindest zu vernachlässigen ist (es sei denn, die Quelldatei und/oder der Datenträger ist stark fragmentiert).

Da es hier um serielle Zugriffe geht, dürfte Multithreading übrigens nicht nur nichts bringen, sondern höchstwahrscheinlich sogar kontraproduktiv sein. Play it simple.

Gast
2012-02-03, 01:41:08
1.) Mehrere Threads sind extrem schädlich, weil dann nicht mehr sequentiell gelesen wird, sondern die Platte (Flaschenhals) abwechselnd zum Anfang bzw. Ende springt.

2.) Die gesamte Datei auf einmal oder in großen Blöcken (z.B. 100MB) einzulesen, ist zwar auf der selben Festplatte schnell, aber sobald du mit 2 Platten arbeitest, verschenkst du Performance, weil du entweder liest oder schreibst.
Der Idealfall wären Blöcke von ca. 32-64KB. Diese sind groß genug, dass sie nicht unnötig I/O Last ans System verursachen und gleichzeitig so klein, dass die read ahead Algorithmen und der Write Cache greifen, womit zur gleichen Zeit eine Platte durchgehend liest und die andere schreibt.

3.) Willst du nur die Daten kopieren oder noch weitere Operationen damit durchführen bzw. wenn ja, wie viel CPU Last machen die Operationen?

4.) Weiters stellt sich die Frage, ob das eine Vordergrundapplikation oder eine Hintergrundapplikation ist. Wenn das Programm im Hintergrund läuft, so würde ich bewusst eine Drossel einbauen mit Wartezeiten (z.B. jedes MB 50ms warten), damit das System nicht total in die Knie geht. Im Gegensatz zur CPU gibt es hier keine Prioritäten und keinen zweiten Kern d.h. wenn du die Platte zu 100% auslastest, ist es mit dem Rest der Arbeit womöglich vorbei.

5.) In jedem Fall sollte es sich bei dem Rechner um Windows Vista SP1 oder neuer handeln. Hier sind oft Performancesteigerungen auf das dreifache möglich. Falls du über das Netzwerk kopierst, zählt die lesende Seite. WinXP hat keinen vernünftigen read ahead Algorithmus.

PatkIllA
2012-02-03, 18:33:36
Du solltest dir asynchrones IO anschauen, damit du gleichzeitig lesen und schreiben kannst bzw das OS das aufteilen kann.
Von .NET gibt es das erst mit 4.5 aber PInvoke ist auch nicht so schwer.
Eigene Threads sind wahrscheinlich eher kontraproduktiv.
Ab Vista gibt es Prioritäten auch für IO.