Episode ini membahas optimasi performa Groovy: menilai trade-off antara dinamis dan statis, memakai @CompileStatic, memanfaatkan invoke dynamic, serta profiling JVM untuk menemukan bottleneck dan meminimalkan overhead runtime.

Groovy dipuji karena fleksibilitasnya, tetapi fleksibilitas memiliki harga: overhead runtime untuk dispatch dinamis. Episode 16 membahas cara mengukur, memahami, dan mengoptimalkan performa script Groovy.
Kalian akan belajar trade-off dinamis versus statis, memakai @CompileStatic, memahami peran invoke dynamic di JVM, serta profiling JVM untuk menemukan bottleneck dan meminimalkan overhead runtime.
Saat Groovy memanggil method secara dinamis, JVM tidak bisa langsung mengetahui method mana yang dieksekusi. Proses pencarian terjadi saat runtime melalui mekanisme seperti CallSite. Ini sangat fleksibel, tetapi menambah overhead dibandingkan pemanggilan statis Java.
Dua teknik utama yang mengurangi overhead:
@CompileStatic memberitahu kompiler Groovy untuk melakukan type checking dan menghasilkan bytecode statis:
import groovy.transform.CompileStatic
@CompileStatic
int totalNilai(List<Integer> nilai) {
nilai.sum()
}
println totalNilai([10, 20, 30])@CompileStatic pada method membuat kompiler memeriksa tipe List<Integer> dan nilai.sum() saat kompilasi. int totalNilai(List<Integer> nilai) menghasilkan bytecode yang setara dengan Java untuk method ini.
Semakin tinggi levelnya, semakin besar penghematan overhead, tetapi semakin sedikit fitur dinamis yang tersedia. Method yang memakai methodMissing atau metaprogramming tidak cocok dengan @CompileStatic.
Perbedaan performa bisa signifikan di hot path. Benchmark sederhana:
import groovy.transform.CompileStatic
@CompileStatic
long loopStatis() {
long total = 0
for (int i = 0; i < 1_000_000; i++) {
total += i
}
total
}
long loopDinamis() {
long total = 0
for (i in 0..<1_000_000) {
total += i
}
total
}
def waktu = { closure ->
def mulai = System.nanoTime()
closure()
(System.nanoTime() - mulai) / 1e6
}
println "Statis: ${waktu { loopStatis() }} ms"
println "Dinamis: ${waktu { loopDinamis() }} ms"def waktu = { closure -> ... } adalah closure pengukur waktu. (System.nanoTime() - mulai) / 1e6 menghitung durasi dalam milidetik. @CompileStatic long loopStatis() biasanya lebih cepat untuk loop seperti ini.
Salah satu overhead tersembunyi adalah pembuatan objek sementara:
int, long, dan double di method @CompileStatic.StringBuilder.GString sangat nyaman, tetapi di hot path lebih cepat memakai StringBuilder:
@CompileStatic
String bangunPesan(int n) {
def sb = new StringBuilder()
for (int i = 0; i < n; i++) {
sb.append("baris ").append(i).append("\n")
}
sb.toString()
}
println bangunPesan(3)sb.append("baris ").append(i) menggabungkan string tanpa membuat objek perantara. @CompileStatic String bangunPesan(int n) memastikan pemanggilan StringBuilder dikompilasi statis.
Profiling dimulai dari pengukuran. JDK menyertakan tool bawaan:
jcmd <pid> GC.heap_info
jconsolejcmd <pid> GC.heap_info menampilkan kondisi heap proses JVM, dan jconsole membuka GUI monitoring real-time. Untuk profiling CPU yang lebih dalam, gunakan async-profiler atau Java Flight Recorder.
jmap -dump:live,format=b,file=heap.hprof <pid>jmap -dump:live,format=b,file=heap.hprof <pid> mengambil snapshot heap yang bisa dianalisis di VisualVM atau Eclipse MAT untuk menemukan objek yang tidak seharusnya bertahan.
Optimasi yang efektif bersifat bertahap:
@CompileStatic pada hot path.Ingat aturan utamanya: kode yang benar dan mudah dibaca lebih berharga daripada kode yang paling cepat tapi tidak terpelihara.
Episode 16 memberikan toolkit optimasi performa Groovy: memahami biaya dynamic dispatch, memakai @CompileStatic di hot path, menghindari objek sementara, serta profiling JVM dengan tool bawaan dan analisis heap dump.
Inti yang harus dibawa pulang:
@CompileStatic menghasilkan bytecode statis ala Java.Di episode 17 selanjutnya kita akan membahas web dan API development — menggunakan Groovy dengan framework seperti Grails atau Micronaut, menulis REST API sederhana dengan JSON serialization, serta deployment ke container, cloud, atau JVM service.