Przetestowałem Javę 12 i Go w benchmarku binarytrees, gdyż jest on dość pesymistycznym przypadkiem jeśli chodzi o automatyczne odśmiecanie.
Na początek wersje:
Wersje oprogramowania:
Kopiuj
$ lsb_release -a
LSB Version: core-9.20160110ubuntu0.2-amd64:core-9.20160110ubuntu0.2-noarch:security-9.20160110ubuntu0.2-amd64:security-9.20160110ubuntu0.2-noarch
Distributor ID: Ubuntu
Description: Ubuntu 16.04.6 LTS
Release: 16.04
Codename: xenial
$ go version
go version go1.6.2 linux/amd64
$ ~/devel/jdk-12/bin/java -version
openjdk version "12" 2019-03-19
OpenJDK Runtime Environment (build 12+33)
OpenJDK 64-Bit Server VM (build 12+33, mixed mode, sharing)
Wyniki wydajności:
Kopiuj
time ./binarytrees.go-5.go_run 21
stretch tree of depth 22 check: 8388607
2097152 trees of depth 4 check: 65011712
524288 trees of depth 6 check: 66584576
131072 trees of depth 8 check: 66977792
32768 trees of depth 10 check: 67076096
8192 trees of depth 12 check: 67100672
2048 trees of depth 14 check: 67106816
512 trees of depth 16 check: 67108352
128 trees of depth 18 check: 67108736
32 trees of depth 20 check: 67108832
long lived tree of depth 21 check: 4194303
real 0m14.385s
user 0m54.290s
sys 0m0.254s
$ time ~/devel/jdk-12/bin/java binarytrees 21
stretch tree of depth 22 check: 8388607
2097152 trees of depth 4 check: 65011712
524288 trees of depth 6 check: 66584576
131072 trees of depth 8 check: 66977792
32768 trees of depth 10 check: 67076096
8192 trees of depth 12 check: 67100672
2048 trees of depth 14 check: 67106816
512 trees of depth 16 check: 67108352
128 trees of depth 18 check: 67108736
32 trees of depth 20 check: 67108832
long lived tree of depth 21 check: 4194303
real 0m2.425s
user 0m7.081s
sys 0m0.726s
$ time ~/devel/jdk-12/bin/java -XX:+UnlockExperimentalVMOptions -XX:+UseZGC binarytrees 21
stretch tree of depth 22 check: 8388607
2097152 trees of depth 4 check: 65011712
524288 trees of depth 6 check: 66584576
131072 trees of depth 8 check: 66977792
32768 trees of depth 10 check: 67076096
8192 trees of depth 12 check: 67100672
2048 trees of depth 14 check: 67106816
512 trees of depth 16 check: 67108352
128 trees of depth 18 check: 67108736
32 trees of depth 20 check: 67108832
long lived tree of depth 21 check: 4194303
real 0m4.068s
user 0m8.820s
sys 0m3.112s
Jak widać Go radzi sobie bardzo słabo. Trzeba jednak wziąć pod uwagę iż ZGC zaalokował sobie sporo pamięci u mnie. Co się stanie jak dam w Javie mniejszą stertę?
G1 GC zachowuje się praktycznie tak samo:
Kopiuj
$ time ~/devel/jdk-12/bin/java binarytrees 21
stretch tree of depth 22 check: 8388607
2097152 trees of depth 4 check: 65011712
524288 trees of depth 6 check: 66584576
131072 trees of depth 8 check: 66977792
32768 trees of depth 10 check: 67076096
8192 trees of depth 12 check: 67100672
2048 trees of depth 14 check: 67106816
512 trees of depth 16 check: 67108352
128 trees of depth 18 check: 67108736
32 trees of depth 20 check: 67108832
long lived tree of depth 21 check: 4194303
real 0m2.425s
user 0m7.081s
sys 0m0.726s
$ time ~/devel/jdk-12/bin/java -Xmx2g binarytrees 21
stretch tree of depth 22 check: 8388607
2097152 trees of depth 4 check: 65011712
524288 trees of depth 6 check: 66584576
131072 trees of depth 8 check: 66977792
32768 trees of depth 10 check: 67076096
8192 trees of depth 12 check: 67100672
2048 trees of depth 14 check: 67106816
512 trees of depth 16 check: 67108352
128 trees of depth 18 check: 67108736
32 trees of depth 20 check: 67108832
long lived tree of depth 21 check: 4194303
real 0m2.402s
user 0m7.495s
sys 0m0.353s
$ time ~/devel/jdk-12/bin/java -Xmx1g binarytrees 21
stretch tree of depth 22 check: 8388607
2097152 trees of depth 4 check: 65011712
524288 trees of depth 6 check: 66584576
131072 trees of depth 8 check: 66977792
32768 trees of depth 10 check: 67076096
8192 trees of depth 12 check: 67100672
2048 trees of depth 14 check: 67106816
512 trees of depth 16 check: 67108352
128 trees of depth 18 check: 67108736
32 trees of depth 20 check: 67108832
long lived tree of depth 21 check: 4194303
real 0m2.465s
user 0m7.857s
sys 0m0.222s
ZGC natomiast sporo zwalnia, ale i tak jest dużo szybsze od Go:
Kopiuj
$ time ~/devel/jdk-12/bin/java -XX:+UnlockExperimentalVMOptions -XX:+UseZGC binarytrees 21
stretch tree of depth 22 check: 8388607
2097152 trees of depth 4 check: 65011712
524288 trees of depth 6 check: 66584576
131072 trees of depth 8 check: 66977792
32768 trees of depth 10 check: 67076096
8192 trees of depth 12 check: 67100672
2048 trees of depth 14 check: 67106816
512 trees of depth 16 check: 67108352
128 trees of depth 18 check: 67108736
32 trees of depth 20 check: 67108832
long lived tree of depth 21 check: 4194303
real 0m4.068s
user 0m8.820s
sys 0m3.112s
$ time ~/devel/jdk-12/bin/java -Xmx2g -XX:+UnlockExperimentalVMOptions -XX:+UseZGC binarytrees 21
stretch tree of depth 22 check: 8388607
2097152 trees of depth 4 check: 65011712
524288 trees of depth 6 check: 66584576
131072 trees of depth 8 check: 66977792
32768 trees of depth 10 check: 67076096
8192 trees of depth 12 check: 67100672
2048 trees of depth 14 check: 67106816
512 trees of depth 16 check: 67108352
128 trees of depth 18 check: 67108736
32 trees of depth 20 check: 67108832
long lived tree of depth 21 check: 4194303
real 0m4.879s
user 0m11.839s
sys 0m1.076s
$ time ~/devel/jdk-12/bin/java -Xmx1g -XX:+UnlockExperimentalVMOptions -XX:+UseZGC binarytrees 21
stretch tree of depth 22 check: 8388607
2097152 trees of depth 4 check: 65011712
524288 trees of depth 6 check: 66584576
131072 trees of depth 8 check: 66977792
32768 trees of depth 10 check: 67076096
8192 trees of depth 12 check: 67100672
2048 trees of depth 14 check: 67106816
512 trees of depth 16 check: 67108352
128 trees of depth 18 check: 67108736
32 trees of depth 20 check: 67108832
long lived tree of depth 21 check: 4194303
real 0m7.458s
user 0m15.141s
sys 0m0.562s
Jeśli dalej przytniemy stertę to ZGC już zwalnia prawie do poziomu Go, chociaż G1 GC nadal utrzymuje wysoką przepustowość:
Kopiuj
$ time ~/devel/jdk-12/bin/java -Xmx500m binarytrees 21
stretch tree of depth 22 check: 8388607
2097152 trees of depth 4 check: 65011712
524288 trees of depth 6 check: 66584576
131072 trees of depth 8 check: 66977792
32768 trees of depth 10 check: 67076096
8192 trees of depth 12 check: 67100672
2048 trees of depth 14 check: 67106816
512 trees of depth 16 check: 67108352
128 trees of depth 18 check: 67108736
32 trees of depth 20 check: 67108832
long lived tree of depth 21 check: 4194303
real 0m3.144s
user 0m9.816s
sys 0m0.197s
$ time ~/devel/jdk-12/bin/java -Xmx500m -XX:+UnlockExperimentalVMOptions -XX:+UseZGC binarytrees 21
stretch tree of depth 22 check: 8388607
2097152 trees of depth 4 check: 65011712
524288 trees of depth 6 check: 66584576
131072 trees of depth 8 check: 66977792
32768 trees of depth 10 check: 67076096
8192 trees of depth 12 check: 67100672
2048 trees of depth 14 check: 67106816
512 trees of depth 16 check: 67108352
128 trees of depth 18 check: 67108736
32 trees of depth 20 check: 67108832
long lived tree of depth 21 check: 4194303
real 0m13.543s
user 0m23.298s
sys 0m0.305s
Dalsze przycinanie byłoby już chyba trochę nie do końca sensowne, bo obiekty w Javie mają raczej trochę większy narzut pamięciowy niż obiekty w Go, a samo ZGC nie jest przygotowane do małych stert.
Shenandoah nie jest dostępne w buildzie od Oracle'a, czyil w buildzie pod adresem: http://jdk.java.net/12/
Kopiuj
$ time ~/devel/jdk-12/bin/java -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC binarytrees 21
Error occurred during initialization of VM
Option -XX:+UseShenandoahGC not supported
real 0m0.005s
user 0m0.000s
sys 0m0.005s