JEDI: Java Evaluation of Declarative and Imperative Queries
Dieser Beitrag stellt JEDI vor, eine automatisch generierte Benchmark-Suite, die SQL-Abfragen in Java übersetzt, um die Leistung deklarativer Stream-API-Implementierungen mit imperativen Baselines zu bewerten und zu vergleichen, mit dem Ziel, ineffiziente Code-Muster zu identifizieren und die Optimierung der Java Stream API zu unterstützen.
Originalarbeit lizenziert unter CC BY 4.0 (http://creativecommons.org/licenses/by/4.0/). Dies ist eine KI-generierte Erklärung des untenstehenden Papers. Sie wurde nicht von den Autoren verfasst oder gebilligt. Für technische Genauigkeit konsultieren Sie das Originalpaper. Vollständigen Haftungsausschluss lesen
Stellen Sie sich vor, Sie haben ein riesiges Lager voller Kartons (Daten), und Sie müssen spezifische Gegenstände finden, sortieren und zählen. Sie haben zwei Möglichkeiten, Ihren Arbeitern Anweisungen zu geben:
- Der „Manager"-Ansatz (Imperativ): Sie gehen zu jedem Arbeiter einzeln hin und sagen: „Nimm diesen Karton auf. Prüfe, ob er rot ist. Wenn ja, leg ihn auf einen Stapel. Wenn nein, wirf ihn weg. Nimm jetzt den nächsten." Das ist sehr direkt und schnell, erfordert aber viel Gespräch und kann chaotisch werden, wenn Sie Tausende von Arbeitern haben.
- Der „Vorarbeiter"-Ansatz (Java Stream API): Sie schreiben eine einzige, elegante Notiz: „Nehmen Sie alle Kartons, filtern Sie die roten heraus, sortieren Sie sie nach Größe und zählen Sie sie." Sie geben diese Notiz einem Vorarbeiter, der herausfindet, wie er die Arbeiter dazu bringt, es zu tun. Das ist für Sie viel einfacher zu schreiben und zu lesen, aber der Vorarbeiter muss Ihre Notiz in Handlungen übersetzen, was manchmal zusätzliche Zeit kostet.
Dieses Papier mit dem Titel JEDI dreht sich darum zu testen, wie gut der „Vorarbeiter" (die Java Stream API) im Vergleich zum „Manager" (traditioneller Code) abschneidet, und herauszufinden, wie man den Vorarbeiter schneller arbeiten lassen kann.
Das Problem
Die Java Stream API ist beliebt, weil sie Code sauber und leicht verständlich macht (wie die Notiz an den Vorarbeiter). Entwickler haben jedoch vermutet, dass diese „saubere" Art, Code zu schreiben, langsamer ist als die „chaotische" traditionelle Methode. Das Problem ist, dass niemand eine ordentliche Rennstrecke (einen Benchmark) hatte, um dies fair zu testen. Ohne eine Rennstrecke wissen die Leute, die die Java-Sprache bauen (die „Mechaniker"), nicht genau, wo der Motor stottert, und Entwickler wissen nicht, welche Anweisungen die beste Geschwindigkeit liefern.
Die Lösung: JEDI
Die Autoren haben JEDI (Java Evaluation of Declarative and Imperative Queries) entwickelt. Denken Sie an JEDI als eine riesige, automatisierte Fabrik, die Standard-Datenbankabfragen (geschrieben in einer Sprache namens SQL, die wie ein universelles Anforderungsformular ist) nimmt und sie sofort in zwei verschiedene Sätze von Anweisungen übersetzt:
- Einen Satz im „Vorarbeiter"-Stil (Streams).
- Einen Satz im „Manager"-Stil (imperative Schleifen).
Da die Fabrik die exakt gleiche Frage in beide Stile übersetzt, ist der Vergleich perfekt fair. Es ist, als würde man zwei Läufern exakt denselben Weg geben und sie stoppen, um zu sehen, wer schneller ist.
Was sie herausfanden
1. Kleine Anpassungen machen einen großen Unterschied (Die „Filter-Fusion")
Manchmal gerät der Vorarbeiter in Verwirrung, wenn Sie ihm drei separate Notizen geben: „Prüfe auf Rot", „Prüfe auf Groß", „Prüfe auf Schwer".
- Die Lösung: Die Autoren stellten fest, dass das Zusammenfassen dieser zu einer großen Notiz („Prüfe auf Rot UND Groß UND Schwer") den Vorarbeiter viel schneller macht. Es ist, als würde man einem Arbeiter eine klare Anweisung geben statt drei verwirrenden.
- Das Ergebnis: Diese einfache Änderung ließ den Code in einigen Fällen bis zu 2,6-mal schneller laufen.
2. Der „Eins-zu-Viele"-Trick
Manchmal enthält ein einzelner Karton viele kleinere Gegenstände.
- Der alte Weg: Der Vorarbeiter würde den Karton nehmen, öffnen, einen Gegenstand herausziehen, auf einen Stapel legen, zurückgehen, den nächsten herausziehen und wiederholen.
- Der neue Weg: Die Autoren fanden ein spezielles Werkzeug (genannt
mapMulti), das es dem Vorarbeiter ermöglicht, den Karton zu öffnen und alle Gegenstände auf einmal in einer flüssigen Bewegung herauszuschütten. - Das Ergebnis: Dies war sogar effektiver als der erste Tipp und verdoppelte oft die Geschwindigkeit.
3. Das Parallelismus-Rätsel (Viele Arbeiter einsetzen)
Wenn Sie ein riesiges Lager haben, wollen Sie viele Arbeiter gleichzeitig einsetzen (parallele Verarbeitung). Das Papier testete vier verschiedene Möglichkeiten, diese Arbeiter zu organisieren:
- Das „Streng geordnete" Team: Alle arbeiten in einer Reihe und geben Kartons weiter. Gut für die Wahrung der Ordnung, aber langsam.
- Das „Chaos"-Team: Alle greifen sich zufällig Kartons. Schnell, aber schwer zu managen.
- Das „Geteiltes Board"-Team: Alle schreiben ihre Ergebnisse auf eine riesige, gemeinsame Whiteboard.
- Das „Atomare" Team: Alle verwenden einen speziellen, hochtechnologischen Stift, der niemals verschmiert, selbst wenn zwei Personen gleichzeitig schreiben.
Das Urteil: Es gibt kein einziges „bestes" Team.
- Wenn Sie sehr wenige Gruppen von Gegenständen zu sortieren haben (wie nur 4 Obstsorten), sind das „Streng geordnete" oder das „Chaos"-Team am schnellsten, weil das „Geteilte Board" zu überfüllt wird (zu viel Streit darüber, wer zuerst schreibt).
- Wenn Sie Tausende von Gruppen haben (wie 10.000 verschiedene Obstsorten), gewinnt das „Geteilte Board"-Team, weil der Streit aufhört und jeder seinen eigenen Abschnitt schreiben kann, ohne andere zu behindern.
4. Die Geschwindigkeitslücke
Die große Frage: Ist der „Vorarbeiter" (Stream) langsamer als der „Manager" (Imperativ)?
- Ja. Der traditionelle „Manager"-Code ist konsequent schneller, normalerweise um etwa 30 % bis 40 %.
- Warum? Der „Vorarbeiter" muss Zeit damit verbringen, Ihre elegante Notiz in Handlungen zu übersetzen. Der „Manager" erledigt die Arbeit einfach sofort.
- Die gute Nachricht: Die Lücke ist nicht so riesig, wie viele in der Vergangenheit dachten. Das Java-Team hat den Motor verbessert. Für die absolut schnellste Leistung gewinnt jedoch immer noch der „Manager"-Stil.
5. Der Kompromiss: Geschwindigkeit vs. Vernunft
Das Papier untersuchte auch, wie schwer der Code zu lesen ist.
- Der „Manager"-Code (schnellste) ist wie ein dichter, verwirrender Handbuch. Er ist schwer zu lesen und anfällig für Fehler.
- Der „Vorarbeiter"-Code (langsamer) ist wie eine klare, kurze Geschichte. Er ist viel leichter zu verstehen und weniger fehleranfällig.
- Die Lehre: Sie müssen wählen. Wollen Sie, dass der Code 30 % schneller läuft, oder wollen Sie, dass er für Menschen 2,5-mal einfacher zu lesen und zu warten ist? Das Papier schlägt vor, dass für die meisten Menschen der „Vorarbeiter"-Stil die kleine Geschwindigkeitseinbuße wert ist, weil er Zeit beim Debugging und bei der Wartung spart.
Zusammenfassung
JEDI ist ein neues Werkzeug, das Entwicklern hilft, die „Kosten" der Verwendung der modernen, leicht lesbaren Java Stream API zu verstehen. Es beweist, dass zwar der leicht lesbare Code etwas langsamer ist als der altmodische Code, Sie ihn aber durch den Einsatz spezifischer Tricks (wie das Kombinieren von Filtern) viel schneller machen können. Es sagt Entwicklern auch genau, wie sie ihre Arbeiter organisieren sollen (Parallelisierungsstrategien), abhängig davon, wie viel Daten sie haben. Letztendlich gibt es Entwicklern eine Landkarte, um Code zu schreiben, der sowohl lesbar als auch angemessen schnell ist.
Ertrinken Sie in Arbeiten in Ihrem Fachgebiet?
Erhalten Sie tägliche Digests der neuesten Arbeiten passend zu Ihren Forschungsbegriffen — mit technischen Zusammenfassungen, in Ihrer Sprache.