JDKのバージョンによる文字列連結処理の速度の違い
過去にもなんか調べた気がしないでもないが、Java 9リリース記念ということで、Sun/Oracle JDK限定だが、JDKのバージョンを変えたときの「+」連結/StringBuffer/StringBuilderの速度の違いをざっと調べてみた。
平均値とか出すのが面倒だったので、測定は一発勝負(ぉ‥
測定環境
CentOS 6のVM(VirtualBox on Windows 10 on Let's Note CF-SX2)上で、以下のJava VMを使って測定(java -versionの出力)。
java version "1.4.2_19" Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_19-b04) Java HotSpot(TM) Client VM (build 1.4.2_19-b04, mixed mode)
java version "1.5.0_22" Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_22-b03) Java HotSpot(TM) Client VM (build 1.5.0_22-b03, mixed mode, sharing)
java version "1.6.0_45" Java(TM) SE Runtime Environment (build 1.6.0_45-b06) Java HotSpot(TM) 64-Bit Server VM (build 20.45-b01, mixed mode)
java version "1.7.0_72" Java(TM) SE Runtime Environment (build 1.7.0_72-b14) Java HotSpot(TM) 64-Bit Server VM (build 24.72-b04, mixed mode)
java version "1.8.0_66" Java(TM) SE Runtime Environment (build 1.8.0_66-b17) Java HotSpot(TM) 64-Bit Server VM (build 25.66-b17, mixed mode)
java version "9" Java(TM) SE Runtime Environment (build 9+181) Java HotSpot(TM) 64-Bit Server VM (build 9+181, mixed mode)
ソースコードはこの後に載せるが、コンパイルは以下のような感じで行った。(Xxxの部分には「Plus」「StringBuffer」「StringBuilder」が入る)
ソースコード
MainNnPlus (Nnの部分には「14」「15」が入る)
public class MainNnPlus { public static void main(String[] args) { int n = args.length > 0 ? Integer.parseInt(args[0]) : 10000; long S = System.currentTimeMillis(); String s = ""; for (int i = 0; i < n; ++i) { s += "a"; } long G = System.currentTimeMillis(); System.out.println(System.getProperty("java.version") + ":" + n + ":" + (G - S)); } }
MainNnStringBuffer (Nnの部分には「14」「15」が入る)
public class MainNnStringBuffer { public static void main(String[] args) { int n = args.length > 0 ? Integer.parseInt(args[0]) : 10000; long S = System.currentTimeMillis(); StringBuffer sb = new StringBuffer(); for (int i = 0; i < n; ++i) { sb.append("a"); } long G = System.currentTimeMillis(); System.out.println(System.getProperty("java.version") + ":" + n + ":" + (G - S)); } }
Main15StringBuilder
public class Main15StringBuilder { public static void main(String[] args) { int n = args.length > 0 ? Integer.parseInt(args[0]) : 10000; long S = System.currentTimeMillis(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < n; ++i) { sb.append("a"); } long G = System.currentTimeMillis(); System.out.println(System.getProperty("java.version") + ":" + n + ":" + (G - S)); } }
実行(測定)
実行(測定)は以下のようなシェルスクリプトを組んで行った。
#! /bin/bash d1=3000 max1=30000 d2=10000000 max2=100000000 ~/jdk/j2sdk1.4.2_19/bin/javac Main14*.java ~/jdk/jdk1.5.0_22/bin/javac Main15*.java for c in Main{14,15}Plus ; do echo === ${c} for ((n = d1; n <= max1; n += d1)); do ~/jdk/run.sh -Xmx1024m ${c} ${n} done done for c in Main{14,15}StringBuffer ; do echo === ${c} for ((n = d2; n <= max2; n += d2)); do ~/jdk/run.sh -Xmx1024m ${c} ${n} done done for c in Main15StringBuilder ; do echo === ${c} for ((n = d2; n <= max2; n += d2)); do ~/jdk/run.sh -Xmx1024m ${c} ${n} done done
~/jdk/run.sh
の中身は以下。
#! /bin/bash d=$(dirname $0) for jdk in j2sdk1.4.2_19 jdk1.5.0_22 jdk1.6.0_45 jdk1.7.0_72 jdk1.8.0_66 jdk-9 ; do if [ -d ${d}/${jdk} ]; then ${d}/${jdk}/bin/java $@ fi done
測定結果
Main14Plus
1.4.2_19 | 1.5.0_22 | 1.6.0_45 | 1.7.0_72 | 1.8.0_66 | 9 | |
---|---|---|---|---|---|---|
3000 | 11 | 19 | 16 | 22 | 15 | 17 |
6000 | 28 | 47 | 63 | 72 | 50 | 36 |
9000 | 57 | 99 | 94 | 103 | 82 | 66 |
12000 | 113 | 190 | 150 | 154 | 131 | 89 |
15000 | 216 | 289 | 235 | 213 | 177 | 116 |
18000 | 357 | 459 | 292 | 225 | 244 | 169 |
21000 | 538 | 742 | 374 | 264 | 331 | 192 |
24000 | 793 | 1064 | 485 | 291 | 402 | 256 |
27000 | 1104 | 1538 | 593 | 319 | 517 | 296 |
30000 | 1469 | 2042 | 726 | 356 | 596 | 352 |
Main15Plus
1.4.2_19 | 1.5.0_22 | 1.6.0_45 | 1.7.0_72 | 1.8.0_66 | 9 | |
---|---|---|---|---|---|---|
3000 | 15 | 17 | 22 | 17 | 16 | |
6000 | 47 | 57 | 70 | 49 | 34 | |
9000 | 103 | 90 | 103 | 78 | 56 | |
12000 | 178 | 144 | 152 | 120 | 85 | |
15000 | 291 | 218 | 196 | 173 | 111 | |
18000 | 476 | 292 | 227 | 253 | 150 | |
21000 | 743 | 380 | 255 | 307 | 182 | |
24000 | 1075 | 494 | 282 | 394 | 232 | |
27000 | 1552 | 613 | 321 | 495 | 291 | |
30000 | 2092 | 751 | 367 | 626 | 353 |
Main14StringBuffer
1.4.2_19 | 1.5.0_22 | 1.6.0_45 | 1.7.0_72 | 1.8.0_66 | 9 | |
---|---|---|---|---|---|---|
10000000 | 389 | 269 | 211 | 208 | 191 | 142 |
20000000 | 771 | 519 | 397 | 422 | 357 | 241 |
30000000 | 1125 | 809 | 542 | 583 | 500 | 339 |
40000000 | 1541 | 1068 | 756 | 828 | 716 | 471 |
50000000 | 1993 | 1310 | 939 | 1009 | 855 | 584 |
60000000 | 2264 | 1564 | 1412 | 1291 | 1053 | 839 |
70000000 | 2704 | 1783 | 1272 | 1379 | 1142 | 760 |
80000000 | 3185 | 2246 | 1789 | 1909 | 1703 | 1034 |
90000000 | 3982 | 3027 | 1837 | 2290 | 1824 | 1070 |
100000000 | 4518 | 3455 | 2542 | 2108 | 1665 | 1120 |
Main15StringBuffer
1.4.2_19 | 1.5.0_22 | 1.6.0_45 | 1.7.0_72 | 1.8.0_66 | 9 | |
---|---|---|---|---|---|---|
10000000 | 369 | 331 | 330 | 272 | 169 | |
20000000 | 544 | 409 | 608 | 523 | 362 | |
30000000 | 778 | 659 | 649 | 487 | 444 | |
40000000 | 1601 | 751 | 1173 | 969 | 444 | |
50000000 | 1305 | 953 | 1101 | 1219 | 762 | |
60000000 | 2030 | 1068 | 1223 | 1413 | 920 | |
70000000 | 2207 | 1359 | 1570 | 1133 | 707 | |
80000000 | 2772 | 1821 | 2046 | 1670 | 889 | |
90000000 | 2589 | 2355 | 2107 | 1924 | 1414 | |
100000000 | 3042 | 2324 | 2224 | 2274 | 1180 |
Main15StringBuilder
1.4.2_19 | 1.5.0_22 | 1.6.0_45 | 1.7.0_72 | 1.8.0_66 | 9 | |
---|---|---|---|---|---|---|
10000000 | 349 | 213 | 203 | 168 | 63 | |
20000000 | 440 | 286 | 331 | 318 | 157 | |
30000000 | 808 | 324 | 315 | 298 | 131 | |
40000000 | 906 | 543 | 655 | 617 | 242 | |
50000000 | 1488 | 817 | 778 | 713 | 252 | |
60000000 | 1388 | 639 | 636 | 687 | 328 | |
70000000 | 2010 | 1032 | 804 | 644 | 266 | |
80000000 | 1782 | 1309 | 1183 | 1047 | 507 | |
90000000 | 2530 | 1117 | 996 | 951 | 387 | |
100000000 | 2694 | 1389 | 1421 | 1413 | 567 |