Optimale Vorgehensweise XML Datei mit Multithreading zu verarbeiten



  • Problem:

    Ich möchte eine ca. 3 GB fette XML Datei auslesen, die eingelesenen Daten verarbeiten und das Ergebnis in eine neue Datei schreiben.

    Damit das schneller geht würde ich das gerne mit mehreren Threads machen.
    Nun frage ich mich, wie ich das am besten mache.

    Ich habe mir das so gedacht. Ich verwende einen einzigen Thread um die Daten von der HD/SSD einzulesen und delegiere dann Häppchenweise 4K Blöcke der Datei an n andere Threads, die bearbeiten dann diese Häppchen und schicken das fertige Ergebnisse an einen weiteren Thread, dieser ist dann allein für das schreiben in die neue Datei zuständig.

    Ist das eine gute Vorgehensweise, dass in Threads aufzuteilen?
    Oder soll ich das zurückschreiben wieder vom ersten Thread machen lassen, weil dieser liest ja von der HD/SSD und die würde ich mit vielen Threads die sich gegenseitig behindern ungerne ausbremsen.



  • Kann man so pauschal nicht sagen. Natürlich ist es nicht gut, auf derselben HDD gleichzeitig eine Datei zu lesen und eine andere zu schreiben. Dabei ist es ziemlich egal, obs derselbe Thread ist oder nicht, die Bewegungen des Schreib-/Lesekopfes sind das Problem. Wär also auf jeden Fall besser, die Daten in großen Blöcken zu lesen und zu schreiben, so 100 MB oder keine Ahnung wie viel.
    Und wo genau kommt hier "Multithreading" ins Spiel? Macht vielleicht Sinn, einen Thread die Daten lesen/schreiben zu lassen (oder zwei, ist wie gesagt egal), und einen anderen die XML zu parsen und zu verarbeiten. Aber das Parsen auf mehrere Threads zu verteilen wird schwierig.



  • Mechanics schrieb:

    Kann man so pauschal nicht sagen. Natürlich ist es nicht gut, auf derselben HDD gleichzeitig eine Datei zu lesen und eine andere zu schreiben. Dabei ist es ziemlich egal, obs derselbe Thread ist oder nicht, die Bewegungen des Schreib-/Lesekopfes sind das Problem.

    Aber ist es bei zwei Threads nicht viel wahrscheinlicher, dass die gleichzeitig auf die Platte zugreifen wollen?
    Insbesondere in Zeiten von Multicore CPUs wechseln sich die Threads ja nicht mehr ab, wie bei Single Core CPUs, sondern können gleichzeitig arbeiten und somit auch versuchen beide auf die HD zuzugreifen, was dann natürlich abwechselnd passieren muss, weil die HD nur ein Kommando zur gleichen Zeit entgegen nehmen kann, aber dann springt ja immer der Kopf hin und her.

    Und wo genau kommt hier "Multithreading" ins Spiel? Macht vielleicht Sinn, einen Thread die Daten lesen/schreiben zu lassen (oder zwei, ist wie gesagt egal), und einen anderen die XML zu parsen und zu verarbeiten. Aber das Parsen auf mehrere Threads zu verteilen wird schwierig.

    Beim Parsen und Strinoperationen sollen die Multithreads zum Zug kommen.



  • Es wird aber nicht jeder Zugriff auf die Festplatte sofort ausgeführt. Es gibt noch genügend Möglichkeiten, da was zu cachen und die Zugriffe umzusortieren. Von dem her sollte es bei deinem vorgeschlagenen Zugriffsmuster (4KB Blöcke) ziemlich egal sein, obs ein Thread ist oder mehrere. Wenn du tatsächlich viel größere Blöcke mit zig MB nimmst, dann kommen sich die Threads sicher in die Quere und dann würd ich nur einen IO Thread machen.
    Ich glaube, ich hab noch nie irgendwas gesehen, das das Parsen von einem einzigen Dokument auf mehrere Threads aufteilen würde.



  • Mechanics schrieb:

    Es wird aber nicht jeder Zugriff auf die Festplatte sofort ausgeführt. Es gibt noch genügend Möglichkeiten, da was zu cachen und die Zugriffe umzusortieren. Von dem her sollte es bei deinem vorgeschlagenen Zugriffsmuster (4KB Blöcke) ziemlich egal sein, obs ein Thread ist oder mehrere. Wenn du tatsächlich viel größere Blöcke mit zig MB nimmst, dann kommen sich die Threads sicher in die Quere und dann würd ich nur einen IO Thread machen.
    Ich glaube, ich hab noch nie irgendwas gesehen, das das Parsen von einem einzigen Dokument auf mehrere Threads aufteilen würde.

    Okay, und wenn ich für jeden Thread anstatt nur 4 KByte von meinem Einlesethread gleich 100 MB einlese und die dann von dem Thread bearbeiten lasse?
    Wie würde es dann aussehen?



  • Kennst du das Consumer Producer Pattern? Könnte man vielleicht so ähnlich machen. Du hast zwei Threads, die gleichzeitig Consumer und Producer sind, und zwei Queues, Eingabedaten und Ausgabedaten. Der Verarbeitungssthread wartet, bis genug Daten in der Eingabequeue sind und schreibt dann die Ausgabe in die Ausgabequeue. Der IO Thread liest die Daten in die Eingabequeue, schaut aber ab und zu nach, ob in der Ausgabequeue genug Daten sind, und wenn ja, schreibt er sie weg. Idealerweise würde er sie wegschreiben, während der Verarbeitungsthread noch genug zu tun hat hat, aber diese Zusatzbedingung wär wohl nicht mehr so einfach umzusetzen.


Anmelden zum Antworten