22 June 2023

Letzten Herbst habe ich ili2c, ilivalidator und ili2pg mit GraalVM zu einem Native Image kompiliert. Daraus resultiert - im Gegensatz zu den offiziell publizierten Versionen - eine betriebssystemabhängige Variante, die jedoch keine Java-Installation benötigt. Das Kompilieren übernimmt eine Github Action und somit können mindestens drei Betriebssysteme (Windows, Ubuntu-Linux, macOS) problemlos angeboten werden.

Einen Haken hat die ganze Sache aber: Die Performance ist massiv schlechter als bei den Java-Varianten. Dies wird vor allem bei der Prüfung mit ilivalidator zum Problem. Es gab bereits relativ lange eine Enterprise-Version von GraalVM, die sich diesem Problem annahm. Die Java-Variante kann in unserem Fall anscheinend massiv vom JIT-Compiler profitieren und während der Laufzeit immer mehr den Code optimieren. Das ist mit einem Native Image nicht mehr möglich. Das muss alles vorher passieren. Dies ist bei der Enterprise-Variante mit «Profile-Guided Optimizations» möglich. Die Anwendung wird zuerst geprofiled und dabei Informationen gesammelt. Mit diesen Informationen wird anschliessend der Native Image Builder gefüttert und daraus sollte eine bessere Performance resultieren. Eine zweite Baustelle ist der Garbager Collector. Die Community-Variante verfügt nur über den Serial GC, die Enterprise-Variante zusätzlich über den Garbage First Garbage Collector (G1GC), jedoch nur unter Linux. Nun hat aber auch die Enterprise-Variante einen Haken und man vermutet wohl richtig: Enterprise == $.

Mit dem neusten GraalVM-Release (Version 23) gibt es keine Enterprise-Variante mehr. Der Nachfolger heisst «Oracle GraalVM» und ist frei. Man sollte sich sicherheitshalber wohl die «GraalVM Free Terms and Conditions (GFTC) license» und die FAQ gut durchlesen.

Mit all den Enterprise-Feature, die nun frei verfügbar sind, steht einem Performance-Vergleich nichts mehr im Wege. Geprüft wird ilivalidator 1.13.3 mit unserem Fruchtfolgeflächen-Datensatz. Zuerst habe ich nur die einzelnen Objekte geprüft (--singlePass). Das hat zur Folge, dass die AREA-Prüfung nicht ausgeführt wird. Als Testrechner habe einen Hetzner-Cloud-Server verwendet.

Variante Dauer (mins:secs)

Standard

1:33

PGO

1:00

PGO und G1GC

1:04

JVM

0:33

Eine spürbare Verbesserung vor allem dank PGO ist sichtbar. Gegen die JVM-Variante haben die Native Images aber immer noch keine Chance. Wie sieht es aus, wenn ich das XTF komplett prüfe (also v.a. inklusive der AREA-Prüfung):

Variante Dauer (mins:secs)

Standard

13:32

PGO

10:13

PGO und G1GC

8:19

JVM

6:08

Die Unterschiede werden grösser. Die PGO+G1GC-Variante ist fünf Minuten schneller als die Standardvariante. Es gibt zwar immer noch eine Lücke zur reinen Java-Variante zu schliessen, aber absolut faszinierend was sich rausholen lässt mit einem anderen Garbage Collector und den PGO.

Wie sieht es bei ili2pg aus? Die Datenbank läuft in einem Docker-Container. Die Prüfung des Datensatzes wurde ausgeschaltet (--disableValidation):

Variante Dauer (mins:secs)

Standard

0:40

PGO

0:35

PGO und G1GC

0:19

JVM

0:20

Es bräuchte wohl grössere Datensätze, um hier grössere Abstände zu sehen. Jedenfalls scheint PGO+G1GC auch hier gut mithalten zu können. Der Einfluss der Anwendung dürfte auf die reine Ausführungszeit geringer sein, da die Datenbank natürlich viel abarbeiten muss.

Die ilitools als Native Image werden immer interessanter und dank der frei verfügbaren Oracle GraalVM Distribution ist die Herstellung auch kein Problem mehr.

Posted by Stefan Ziegler. | INTERLIS , Java , GraalVM