HHeLiBeXの日記 正道編

日々の記憶の記録とメモ‥

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

f:id:hhelibex:20171024225451p:plain

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

f:id:hhelibex:20171024225701p:plain

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

f:id:hhelibex:20171024225800p:plain

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

f:id:hhelibex:20171024225915p:plain

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

f:id:hhelibex:20171024230039p:plain