Daten von der Festplatte lesen, bringen Threads einen Zeitgewinn?



  • Hallo,

    ich habe hier eine Datei, die ist 1.4gb groß. Diese muss ich komplett parsen und dann Datenstrukturen erzeugen. So wie das für mich aussieht, ist der Flaschenhals hier die Festplatte. Gibt es irgendeinen Ansatz, wie ich die Datei schneller verarbeiten könnte?

    Hätte an Threads gedacht, oder an Aufteilen der Datei+Threads. Aber das Problem wird ja der Lesezeiger sein, der dann noch wilder umherspringen muss und so wird es wohl am Ende langsamer.

    Gibt es andere Ansätze?



  • Ein grooooßer Lesepuffer, oder gleich die ganze Datei ins RAM lasden.



  • Du musst die Daten von Anfang bis Ende linear durchlesen. Rumspringen ist Blödsinn, das vernichtet dir die Performance. Das OS wird zwar halbwegs gut cachen, aber selbst im best Case machst du dabei unnötig viele Kernel Calls.

    Lesezeiger schrieb:

    So wie das für mich aussieht, ist der Flaschenhals hier die Festplatte.

    Implementier' das ganze erstmal. Wenn du die 500MB/s die ne übliche SATA SSD schafft hinbekommst kannst du dir weiter Gedanken machen.



  • DirkB schrieb:

    Ein grooooßer Lesepuffer, oder gleich die ganze Datei ins RAM lasden.

    Bringt nix beim linearen Lesen. So ab 4 bis 8k hört's auf, spürbar schneller zu werden.



  • @volkard
    Echt?
    Muss ich nochmal probieren dann.
    Ich hab (vor vielen Jahren, zugegeben) mal ne Benchmark gemacht, und da war der Knick bei ca. 0.5 MB.
    Wobei ich da lesen->verarbeiten->lesen->verarbeiten->... gemacht habe. D.h. das ganze hat sich für gute Performance auf Read-Ahead des OS und der HDD verlassen.

    Mit ner Producer-Consumer Queue dazwischen hätte das Ergebnis vielleicht wieder anders ausgesehen.



  • hustbaer schrieb:

    @volkard
    Echt?

    Ich hatte ganz schlanke Verarbeitung wie CRC32 oder Rausleser der Zeilen, die mit einem '*' beginnen. Naja, JSON-ähnliches Format lesen muss auch nicht lahmer als CRC32 sein (schnelles new, hex statt dez).
    Schon auf DOS waren die Messungen wie beschrieben. Auf WinXP hab ich auch ganz ausführlich gemessen, auch gegen filemapping und ReadFileScatter. Nichtmal die bringen einen Deut. Ab 4 oder 8k und ganz schlichtem ReadFile war ich nur noch 1% vom Optimum entfernt.



  • Komisch.
    Ich hatte mit Win2K gemessen und meine Verarbeitung war auch CRC32.
    Und wie gesagt: bis 0.5 MB Puffergrösse ne deutliche Steigerung.
    😕



  • Lesezeiger schrieb:

    Hallo,

    ich habe hier eine Datei, die ist 1.4gb groß. Diese muss ich komplett parsen und dann Datenstrukturen erzeugen. So wie das für mich aussieht, ist der Flaschenhals hier die Festplatte. Gibt es irgendeinen Ansatz, wie ich die Datei schneller verarbeiten könnte?

    Das kann nur wenige Sekunden dauern. Warum muss so eine kleine Datei unbedingt besonders schnell verarbeitet werden?
    Ist das wirklich eine "Festplatte" oder ein SSD?
    Ist die Datei schon im Cache des Betriebssystems oder eher nicht?

    Lesezeiger schrieb:

    Hätte an Threads gedacht, oder an Aufteilen der Datei+Threads. Aber das Problem wird ja der Lesezeiger sein, der dann noch wilder umherspringen muss und so wird es wohl am Ende langsamer.

    Gibt es andere Ansätze?

    Wenn du die linear liest, verlass dich auf das Prefetching, das moderne Betriebssysteme standardmäßig machen. Du brauchst also nur einen Thread.
    Meide aufgeblähte Wrapper wie fread oder fstream und verwende stattdessen die plattformspezifischen Funktionen.
    Die optimale Größe des Lesepuffers musst du für deine Plattform und Anwendung selber ermitteln.
    Wenn die Datei in der Regel bereits im Cache des Betriebssystemes liegt, solltest du ausprobieren die in deinen Prozess mappen, weil das Systemaufrufe und das Kopieren der Daten in den Userspace spart. Eventuell musst du deinem Betriebssystem sagen, dass alle Pages linear durchlaufen werden. Das spart dann Page Faults.



  • das schnellste bei sowas duerfte read only memory mapped files sein (da das dann als auslagerungsdatei vom OS bedient wird und somit eh ein hintergrundsthread, DMA etc. in page chunks geladen wird).
    Das in kombination mit einem schnellen LZ entpacker, damit kannst du, je nach CPU und implementierung, mehrere GB/s entpacken.

    falls du die datei oefters nutzt, aber die applikation sporadisch startet (z.b. oldschool CGI), kannst du auch eine ram-disk anlegen, wenn du die memory mapped oeffnest, wird das OS den physikalischen speicher zwischen beliebig vielen processes teilen.



  • Ach, ja, bei meinen Messungen hab ich natürlich

    TyRoXx schrieb:

    Meide aufgeblähte Wrapper wie fread oder fstream und verwende stattdessen die plattformspezifischen Funktionen.

    und

    TyRoXx schrieb:

    Eventuell musst du deinem Betriebssystem sagen, dass alle Pages linear durchlaufen werden.

    (CreateFile mit FILE_FLAG_SEQUENTIAL_SCAN)
    beherzigt.


  • Mod

    Um mal meinen Senf dazu zu geben: Ich habe schon öfters Festplatten mit dd kopiert und dabei jeweils vorher angetestet, welche Blockgrößen optimal sind, bevor ich den stundenlangen Vorgang dann laufen ließ. Die default-Blockgröße von 512 Byte ist viel zu klein. Ich habe aber fest gestellt, dass auch jenseits der 8k noch wesentliche Leistungssteigerungen möglich sind. Nicht mehr die extrem großen Leistungssteigerungen (512->8k kann locker eine Größenordnung ausmachen), aber 30% kann man nochmals locker raus holen. Das Optimum war in der Regel bei wenigen bis mehreren hundert kB. Es schadete aber auch nicht sonderlich, wenn man was größeres, wie 1 MB genommen hat. Mag dann zwar ein paar Prozent langsamer sein als das Optimum, aber man sinkt auch nicht mehr auf das 8k-Niveau herab.

    Meine Erfahrungen sind für klassische Magnetplatten. dd macht natürlich überhaupt gar nichts mit den Daten, außer sie kurz zwischen zu lagern.



  • @volkard
    Ich hatte damals auch CreateFile+ReadFile verwendet. Mit und ohne FILE_FLAG_SEQUENTIAL_SCAN probiert, hat keinen Unterschied gemacht. FILE_FLAG_NO_BUFFERING hab' ich auch probiert, hat (wie erwartet, wegen deaktiviertem read-ahead) ein wenig geschadet.

    @SeppJ
    Das deckt sich dann ja ziemlich genau mit dem was ich beobachtet habe (auch wenn ich es nicht so detailiert hier beschrieben habe wie du :-)).
    512K war wie gesagt damals der Winner (hab nur 2**n Grössen durchprobiert). Dass die Unterschiede pro Verdoppelung ab einigen zig kB sehr viel geringer wurde, aber halt immer noch deutlich sichtbar, kann ich auch bestätigen.
    Und auch den leichten Performanceabfall bei > Idealgrösse kann ich bestätigen.


Anmelden zum Antworten