Welcher Java-Programmierer kennt das nicht: man entwickelt ein Programm mit einem hochgradig parallelen Algorithmus, der auch auf hunderten CPUs skalieren kann. Nur hat man im Allgemeinen einen solchen Rechner mit solch einer gut ausgestatteten JVM nicht zur Verfügung, vor allem nicht während der Entwicklungszeit, sondern bestenfalls den eigenen Quadcore im Entwicklungsrechner und noch ein paar andere Rechner, seien es die von Familie und Freund/in oder ausrangierte Bastelrechner. Über Netzwerk zusammengeschlossen bilden sie das, was man als heterogenen Cluster kennt. Mit Java ist es allerdings mit Bordmittel nicht so einfach, diese Ressourcen anzusprechen, da sie nicht mehr in einer JVM laufen, mit einem simplen new Thread() kann man die CPU auf einem anderen Rechner nicht ansprechen. Auch die Umkonfiguration des Programms, sollte mal ein weiterer Rechner dazukommen oder das Programm in Produktion auf den oben erwähnten 100-CPU-Rechner laufen, ist nicht trivial.

Hier setzt das Akka-Framework an, das auf dem Aktoren-Modell basiert. Ein Aktor ist, kurz gesagt, ein unabhängiger Arbeiter mit einem Postfach. Aktoren kommunizieren untereinander mit Nachrichten (immutable!) und gemeinsam bilden sie ein Aktoren-System. Das Akka-Framework stellt solch ein Ökosystem zur Verfügung, das sich – hier kommt der Clou – auch über mehrere JVMs über mehrere Rechner erstrecken kann, natürlich vorausgesetzt, sie sind im selben Netzwerk; Akka spricht dann von Remote-Aktoren. Und das Beste: kommt mal ein Rechner dazu (oder auch 10), ändert sich nicht das Programm, sondern nur eine Konfigurationsdatei.

Benchmark

Getestet habe ich Akka mit einem einfachen Benchmark-Programm, das 1.000.000.000 mal eine Gauss-standardverteilte Zufallszahl mit dem Durchschnittswert 0 und der Standardabweichung 1 aufaddiert. Diese Berechnung kann einfach auf mehrere Threads/Aktoren aufgeteilt werden (Stichwort: embarrassingly parallel).

Der Code für Akka teilt sich dabei in zwei Klassen auf:

Der WorkingActor bekommt mitgeteilt, wie viele Zufallszahlen er berechnen soll und gibt die Summe zurück.

Das Hauptprogramm RoutedAkkaCalculator liest die Akka-Konfiguration ein, ermittelt die Aktoren, auf die das Arbeitspaket verteilt werden soll, verschickt das Arbeitspaket, sammelt die Teilergebnisse ein und akkumuliert sie und gibt am Ende die Laufzeit aus.

Zum Vergleich wurde der selbe Algorithmus auch mit Java-Threads parallelisiert.

Auswertung

Nach einigen Tests hat sich gezeigt: der Overhead von Akka verglichen mit den Java-Bordmitteln zur parallelen Programmierung ist vernachlässigbar (gemessen auf einer JVM). Interessant wird es im Cluster. Dafür habe ich die folgenden 3 Systeme verwendet:

System 1 (Notebook) System 2 (Desktop) System 3 (VM)
CPU (Cores/Threads) 2/4 4/4 4/4
Frequenz 2,8-3,5 GHz (Turbo) 2,4 GHz 2 GHz
RAM 8 GB 8 GB 384 MB

Die Integration in den Benchmark ist einfach über die Konfiguration möglich und das Programm skaliert weiter.

Ergebnisse im Cluster

Ergebnisse des Benchmark-Programms in einem Akka Cluster

Allerdings: In diesem heterogenen (Familien-)Cluster skaliert das Programm nicht so gut wie es könnte, denn es gibt keine automatische Lastverteilung out-of-the-box. Das langsamste System (hier System 3) limitiert also die Skalierung des ganzen Clusters.

Aber auch abseits der Skalierungsprobleme gibt es einige Probleme bei der Entwicklung mit Akka: Ein Problem für den Java-Programmierer ergibt sich dadurch, dass Akka in Scala entwickelt wurde und ScalaDoc nicht kompatibel zu JavaDoc ist. Mit überladenen Methoden stellt sich dann zu oft die Frage: nehme ich Methode(arg1, arg2) oder Methode(arg1, arg2, arg3)? Und was machen überhaupt diese Parameter? Also die Dokumentation von Akka in einem Browser öffnen, die gibt es für Scala und Java – nur leider ist die von Java nicht so umfangreich, einige Funktionen gibt es nur in Scala. Alternative Beispielanwendungen: viele nur in Scala, mit sbt-Build und Verweis auf Play: abschreckend für Java-Entwickler mit Hang zu Maven und Eclipse.

Aber auch andere Hindernisse sind mir bei der Evaluierung des Frameworks über den Weg gelaufen: Akka 2.1.x schickt 4 Nachrichten an Remote-Aktoren, es kommen 2-4 Nachrichten gaußverteilt an. Firewall ausschalten löst das Problem nicht, Google kennt es nicht, erst mit Akka 2.2.x kommen die Nachrichten zuverlässig an bei unverändertem Code.

Schließlich das letzte Problem: Was programmiere ich mit Akka? Die üblichen Fork-Join-Algorithmen sind nicht sehr intuitiv mit Akka umsetzbar, ein Pipeline-Algorithmus wäre optimal – mir persönlich fällt nur gerade keiner ein (mal abgesehen von MPEG-Video-Komprimierung, war mir für die Evaluation aber zu umfangreich 😉 ).

Fazit: Die Idee hinter Akka ist super, nur leider fällt mir in der Praxis kein Einsatz für Akka ein – und im Java EE-Umfeld ist Akka sowieso verboten.

Leave a Comment

By continuing to use the site, you agree to the use of cookies. more information

The cookie settings on this website are set to "allow cookies" to give you the best browsing experience possible. If you continue to use this website without changing your cookie settings or you click "Accept" below then you are consenting to this.

Close