Parallel XML Parsing in Java
Ich Schreibe eine Anwendung, welche die Prozesse, die eine Menge von xml-Dateien (>1000) mit tiefen Knoten-Strukturen. Es dauert etwa sechs Sekunden mit woodstox (Event, API) zum Parsen einer Datei mit 22.000 Nodes.
Der Algorithmus wird in einem Prozess mit der Benutzer-Interaktion, wo nur ein paar Sekunden Reaktionszeit akzeptabel sind. Also muss ich verbessern, die Strategie im Umgang mit den xml-Dateien.
- Meine Prozess-Analyse der xml-Dateien (in Auszügen, nur wenige Knoten).
- Extrahierten Knoten verarbeitet werden und das neue Ergebnis ist geschrieben in einem neuen Datenstrom (was eine Kopie des Dokuments mit geänderten Knoten).
Ich denke jetzt über eine Multithread-Lösung (die besser skaliert auf 16 Core+ hardware). Ich dachte über die folgenden stategies:
- Erstellen mehrerer Parser und laufen parallel auf den xml-Quellen.
- Umschreiben meine parsing-Algorithmus thread-save zu verwenden, die nur eine Instanz des parser (Fabriken, ...)
- Teilen Sie die XML-Quelle in Stücke und ordnen Sie die Abschnitte in mehrere verarbeitungsthreads (map-reduce xml - serial)
- Optimierung meines Algorithmus (besser StAX-parser als woodstox?) /Mit einem parser mit build-in Parallelität
Ich möchte zu verbessern, die Leistung insgesamt und die "pro Datei" Leistung.
Habt Ihr Erfahrung mit solchen Problemen? Was ist der beste Weg zu gehen?
- Es ist nicht klar, was muss maximiert werden hier... die performance auf eine EINZELNE Datei, oder die gesamte Leistung auf alle 1000 Dateien.
- Noch eine Anregung: wenn du Quantifizierung der Größen von Dateien, damit die Berechnung des ganzen (Megabyte pro Sekunde verarbeitet) kann es geben, eine Vorstellung der erwarteten Leistung. Ich erhalten in der Regel 10 - 40 MB/s für das Parsen mit Woodstox beim testen; aber meine Festplatten liefern nur 5 - 10 MB/s erreichte Geschwindigkeit.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Dieser ist offensichtlich: erstellen Sie einfach mehrere Parser und führen Sie Sie parallel in mehreren threads.
Werfen Sie einen Blick auf Woodstox Leistung (momentan down ist, versuchen Sie, google-cache).
Diese kann getan werden, WENN die Struktur des XML ist vorhersehbar: wenn es eine Menge von der gleichen top-level-Elemente. Zum Beispiel:
In diesem Fall könnten Sie das erstellen von einfachen splitter, sucht
<element>
um und speist diese zum Teil auf einen bestimmten parser-Instanz. Das ist ein vereinfachter Ansatz: im realen Leben würde ich mit RandomAccessFile zu finden, start-stop-Punkte (<element>
) und erstellen Sie benutzerdefinierte FileInputStream, die nur arbeitet auf einem Teil der Datei.Werfen Sie einen Blick auf Aalto. Die gleichen Jungs, die erstellt Woodstox. Diese sind Experten in diesem Bereich - das Rad nicht neu erfinden.
Ich Stimme mit Jim. Ich denke, dass, wenn Sie wollen, um die Leistung zu verbessern die Allgemeine Verarbeitung von 1000 Dateien, die Ihr plan ist gut, bis auf #3, das ist in diesem Fall irrelevant.
Wenn Sie jedoch möchten, um die Leistung zu verbessern der Analyse der einzelnen Datei Sie haben ein problem. Ich weiß nicht, wie es möglich ist, split XML-Datei, ohne es analysieren. Jeder chunk wird illegal sein, XML und Ihre parser-Fehler.
Ich glaube, dass die Verbesserung der gesamten Zeit ist gut genug für Sie. In diesem Fall dieses tutorial Lesen:
http://download.oracle.com/javase/tutorial/essential/concurrency/index.html
dann erstellen thread-pool von z.B. 100 threads und queue-enthält XML-Quellen. Jeder thread geparst werden nur 10 Dateien, bringt schwerwiegende performance-Vorteil im multi-CPU-Umgebung.
Zusätzlich zu den bestehenden guten Vorschläge, es ist eine ziemlich einfache Sache zu tun: verwenden Sie den cursor-API (XMLStreamReader), NICHT-Event-API. Event API fügt 30-50% Aufwand ohne (nur IMO) deutlich machen, einfachere Verarbeitung. In der Tat, wenn Sie wollen Komfort, würde ich empfehlen, mit StaxMate statt; es baut auf der Cursor-API ohne Zugabe von erheblichen overhead (höchstens 5-10% im Vergleich zu handgeschriebenen code).
Nun: ich nehme an, Sie haben getan, grundlegende Optimierungen mit Woodstox; aber wenn nicht, check out "3 Einfache Regeln für Schnellen XML-Verarbeitung mit Stax". Speziell, Sie absolut sollte:
Der Grund, warum ich erwähne dies ist, dass, während diese machen keinen funktionalen Unterschied (code wie erwartet funktioniert), können Sie machen große performance-Unterschied; obwohl mehr so bei der Verarbeitung kleiner Dateien.
Ausführen mehrerer Instanzen macht auch Sinn; obwohl in der Regel mit höchstens 1 thread pro Kern. Aber Sie werden nur profitieren, solange Ihre storage-I/O unterstützen können solche Geschwindigkeiten, wenn die Festplatte ist der Flaschenhals dies wird nicht helfen, und kann in einigen Fällen verletzt (wenn Suchvorgänge auf der Festplatte zu konkurrieren). Aber es ist einen Versuch Wert.