```markdown # NijmegenJUG september 2026 ## Java is echwel snel! > Als je snelle software wil hebben moet je tegen Merijn zeggen dat Java traag is prof. Kees Koster, ca 2010 --- # Wie is Merijn - Merijn Vogel - <3 low-level shenanigans - Werk bij First8 (met bijbaan in middelbaar onderwijs) - Sinds 1999 betrokken bij First8, beargumenteerbaar nu voor de vierde[*] keer [*]: ik leg met alle plezier uit hoe dat zit bij een borrel --- # Green IT: Is 'snel' belangrijk? Software die efficient is, gebruikt minder stroom; zo simpel is het... En in andere gevallen is throughput belangrijk, hoeveel kun je per seconde doen; soms is tijdsduur belangrijk, sub 10ms response tijden. En bovendien: dit is cool 8-) en zelfs dat is al genoeg voor een bijeenkomst als deze --- # The rabbithole Avontuurlijke route die ons leidt - van python - via assembly - dieper naar cpu-architectuur - via java - naar een conclusie --- # Het "domme" voorbeeld We gaan de getallen van 0 t/m MAX_INT optellen door een simpele loop. Puur als voorbeeld. Aanleiding was dat ik dit iemand zag doen met python, en dat minder snel was dan ik dacht. Dus vroeg me af hoe snel Java zou zijn. ```python maxint = (2 ** 31 - 1); s = 0; for i in range(0, maxint): s = s + i; print("sum: {}\n".format(s)); ``` --- # Zelfde voorbeeld, andere uiterste: asssembly > Echte programmeurs programmeren in assembly de rest is vals spelen -- Merijn, ca 1988, c64-tijdperk Hoe snel is een computer eigenlijk? Hoe snel zou dat worden? --- # Zelfde voorbeeld, andere uiterste: asssembly > Echte programmeurs programmeren in assembly de rest is vals spelen -- Merijn, ca 1988 ```txt mov rax, 0 mov rcx, 0 loop: add rax, rcx inc rcx cmp rcx, 0x7fffffff jl loop ``` --- # bewijs dat het C programma de assembly bevat ```bash # compile to executable gcc fast.c -o fast # disassemble executable objdump -m i386:x86-64 -Mintel,x86-64 -d fast ./fast ``` --- # Tussenstand 2 Python: ca. 2m30s, dat moet beter kunnen Assembly: ca 0.5s, dat is indrukwekkend --- # Dat was snel!? Tijd voor een duikje nog dieper onder de motorkap: ```bash perf stat -e task-clock,cycles,instructions,branches ./fast ``` Dit geeft ons het aantal cpu-cycles, uitgevoerde cpu-instructies en branches voor een programma --- # Hoe was dat *zo* snel!? 2 *miljard* dingen optellen in 0.5 seconden is 4 *miljard* dingen per seconde doen!? #hoedan --- # CPUs zijn 'slim' - Pipelined: alle fases van een instructie worden parallel uitgevoerd - Meerdere parallele eenheden *per core* voor rekenen en logica (ALUs) - Volgorde mag afwijken - Branch prediction: de `jl` instructie [https://chipsandcheese.com/p/amds-zen-4-part-1-frontend-and-execution-engine](https://chipsandcheese.com/p/amds-zen-4-part-1-frontend-and-execution-engine) ```asm loop: add rax, rcx inc rcx cmp rcx, 0x7fffffff jl loop ``` --- # Java! ```java ///import java.util.stream.LongStream; ///class Fast { /// public static void main(String[] args) { /// LongStream.range(0, 10) /// .forEach(i -> { /// System.out.println(i + " sum: " + sumNaive()); /// }); /// } public static long sumNaive() { long sum = 0; for(int i = 0; i < Integer.MAX_VALUE; i++) { sum += i; } return sum; } ///} ``` Ok, hoe snel zou java zijn? --- # Java was (bijna) net zo snel! En, als we `perf stat` gebruiken blijkt dat die dat doet met MINDER instructies!? Dus in die zin is Java zelfs *efficienter*. Laten we eens dieper onder de motorkap kijken van Java: ```bash java -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly HowFast ``` Helaas print dat bytes en niet de assembly `hsdis` library heb ik in de laatste 15 jaar 1x werkend gekregen... Enkele shell scripts to the rescue! --- # Naief programmeren, de JVM regelt het Je moet niet extra dom programmeren: wat je doet maakt wel degelijk uit. Maar als het er "gewoon" uitziet, dan is het waarschijnlijk performant genoeg. > Als jullie, ontwikkelaars, "gewoon" programmeren, dan optimaliseren wij dat wel. Als jullie 'slim' doen, moeten wij NOG slimmer zijn Panel van JWM ontwikkelaars, JavaOne, 2007 --- ```