聞こえないJavaエンジニアが適当に書き連ねていく

つらつらとメモしたり日頃の溜まっている想いを吐き出す場所です。

JavaOne2017に日本から参加した方々のブログ記事まとめ

個人的なメモです。

gihyo.jp に掲載されているレポート

http://gihyo.jp/news/report/01/JavaOne2017

Publickey(@Publickey)

http://www.publickey1.jp/blog/17/javaone_2017_keynote.html http://www.publickey1.jp/blog/17/javaproject_amberjavaone_2017.html

Takaaki Sugiyama さん(@zinbe)

http://nebuta.hatenablog.jp/entry/2017/10/02/161954 http://nebuta.hatenablog.jp/entry/2017/10/04/233841 http://nebuta.hatenablog.jp/entry/2017/10/07/205217

きしださん(@kis)

http://d.hatena.ne.jp/nowokay/20171002#1507028477 http://d.hatena.ne.jp/nowokay/20171003#1507163551 http://d.hatena.ne.jp/nowokay/20171004#1507329281 http://d.hatena.ne.jp/nowokay/20171005#1507599558

新・小僧さん(@toastkidjp)

https://reminiscencesoftoastkid.tumblr.com/post/165957550938/javaone-2017-day-1-flash-report https://reminiscencesoftoastkid.tumblr.com/post/165993641483/javaone-2017-day2-flash-report https://reminiscencesoftoastkid.tumblr.com/post/166028869458/javaone-2017-day3-flash-report https://reminiscencesoftoastkid.tumblr.com/post/166063657828/javaone-day4-flash-report https://reminiscencesoftoastkid.tumblr.com/post/166097265923/javaone-day-5-flash-report

よこなさん(@ihcomega)

http://ihcomega.hatenadiary.com/entry/2017/10/02/182157 http://ihcomega.hatenadiary.com/entry/2017/10/06/082500

まーやさん(@maaya8585)

https://hotchpotchj37.wordpress.com/2017/10/02/javaone-2017-1%E6%97%A5%E7%9B%AE%E3%83%8F%E3%82%A4%E3%83%A9%E3%82%A4%E3%83%88/ https://hotchpotchj37.wordpress.com/2017/10/03/javaone-2017-2%E6%97%A5%E7%9B%AE-%E3%83%8F%E3%82%A4%E3%83%A9%E3%82%A4%E3%83%88/

Java9のモジュール化について考えてみた #java9

これは何か

モジュール化のメリットがよくわからなかったので、実際に手を動かしながら考えてみた。

seasar2時代から発展していない時代遅れの脳だと、以下の構成がしっくり来た。

モジュールの分け方

actionModule、formModule、serviceModuleの3つに分けてみる。

  • actionModuleはformModuleとserviceModuleを参照できる。
  • formModuleはactionModuleからしか参照できない。
  • serviceModuleはactionModuleから参照できない。

これで、xxxFormをうっかり(わざと?)serviceModule内で参照することを防ぐことができる。

または、formModuleでの入力チェックを行うために、serviceModuleを呼び出してしまうという事故も防げる。

お互いのモジュールの役割分担が出来るので、役割が分かりやすくなるかもしれない。

クラスパスの制御でもそれ出来るんじゃん?

今までは確かにクラスパスに追加する/しないでコントロールできたが、モジュール作成者の意図に沿ったものとは限らなかった。

今回、module-info.javaに依存関係を明記できるようになったことで、モジュール作成者の意図が伝えやすくなる。

思考をまとめてた時のソース

aaaActionModule

package action.project;

import form.project.Form;
import service.project.Bean;
import service.project.Service;

public class Action {

    public static void main(String... args) {
        Form form = new Form();
        form.setName("aaa");

        Bean bean = new Bean();
        bean.setName(form.getName());
        Service service = new Service();
        service.execute(bean);
    }

}
module aaaActionModule {
    requires aaaFormModule;
    requires aaaServiceModule;
}

aaaFormModule

package form.project;

public class Form {

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    private String name;

}
module aaaFormModule {
    exports form.project to aaaActionModule;
}

aaaServiceModule

package service.project;

public class Bean {

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    private String name;

}
module aaaServiceModule {
    exports service.project to aaaActionModule;
}

参考にしたサイト

qiita.com

d.hatena.ne.jp

java.util.ObjectsクラスにcheckIndex()なるメソッドが増えてた話 #java9

序章

Java1.8とJava9のArrayListのソースを比較していたところ、set(int index, E element)/get(int)メソッドの中身が変わっていることに気づきました。

setメソッド

  • Java1.8
public E set(int index, E element) {
    rangeCheck(index);

    E oldValue = elementData(index);
    elementData[index] = element;
    return oldValue;
}
  • Java9
public E set(int index, E element) {
    Objects.checkIndex(index, size);
    E oldValue = elementData(index);
    elementData[index] = element;
    return oldValue;
}

getメソッド

  • Java1.8
public E get(int index) {
    rangeCheck(index);

    return elementData(index);
}
  • Java9
public E get(int index) {
    Objects.checkIndex(index, size);
    return elementData(index);
}

Objectsクラスを見てみる

ObjectsクラスにcheckIndex()なるメソッドが追加されたようです。中身を見てみます。

/**
    * Checks if the {@code index} is within the bounds of the range from
    * {@code 0} (inclusive) to {@code length} (exclusive).
    *
    * <p>The {@code index} is defined to be out-of-bounds if any of the
    * following inequalities is true:
    * <ul>
    *  <li>{@code index < 0}</li>
    *  <li>{@code index >= length}</li>
    *  <li>{@code length < 0}, which is implied from the former inequalities</li>
    * </ul>
    *
    * @param index the index
    * @param length the upper-bound (exclusive) of the range
    * @return {@code index} if it is within bounds of the range
    * @throws IndexOutOfBoundsException if the {@code index} is out-of-bounds
    * @since 9
    */
@ForceInline
public static
int checkIndex(int index, int length) {
    return Preconditions.checkIndex(index, length, null);
}

Preconditionsなる慣れないクラスが出てきました。
どうやら、Java9で新たに追加されたクラスの様で、パッケージは jdk.internal.util です。
なんとなく、一般開発者はあまり直で触らない方がよさそうな雰囲気のパッケージ名です。深入りせずに、戻ることにします。

Objectsクラスに戻ってみると、checkIndex()メソッド以外にcheckFromToIndex()や、checkFromIndexSize()というメソッドも追加されています。

/**
    * Checks if the sub-range from {@code fromIndex} (inclusive) to
    * {@code toIndex} (exclusive) is within the bounds of range from {@code 0}
    * (inclusive) to {@code length} (exclusive).
    *
    * <p>The sub-range is defined to be out-of-bounds if any of the following
    * inequalities is true:
    * <ul>
    *  <li>{@code fromIndex < 0}</li>
    *  <li>{@code fromIndex > toIndex}</li>
    *  <li>{@code toIndex > length}</li>
    *  <li>{@code length < 0}, which is implied from the former inequalities</li>
    * </ul>
    *
    * @param fromIndex the lower-bound (inclusive) of the sub-range
    * @param toIndex the upper-bound (exclusive) of the sub-range
    * @param length the upper-bound (exclusive) the range
    * @return {@code fromIndex} if the sub-range within bounds of the range
    * @throws IndexOutOfBoundsException if the sub-range is out-of-bounds
    * @since 9
    */
public static
int checkFromToIndex(int fromIndex, int toIndex, int length) {
    return Preconditions.checkFromToIndex(fromIndex, toIndex, length, null);
}

/**
    * Checks if the sub-range from {@code fromIndex} (inclusive) to
    * {@code fromIndex + size} (exclusive) is within the bounds of range from
    * {@code 0} (inclusive) to {@code length} (exclusive).
    *
    * <p>The sub-range is defined to be out-of-bounds if any of the following
    * inequalities is true:
    * <ul>
    *  <li>{@code fromIndex < 0}</li>
    *  <li>{@code size < 0}</li>
    *  <li>{@code fromIndex + size > length}, taking into account integer overflow</li>
    *  <li>{@code length < 0}, which is implied from the former inequalities</li>
    * </ul>
    *
    * @param fromIndex the lower-bound (inclusive) of the sub-interval
    * @param size the size of the sub-range
    * @param length the upper-bound (exclusive) of the range
    * @return {@code fromIndex} if the sub-range within bounds of the range
    * @throws IndexOutOfBoundsException if the sub-range is out-of-bounds
    * @since 9
    */
public static
int checkFromIndexSize(int fromIndex, int size, int length) {
    return Preconditions.checkFromIndexSize(fromIndex, size, length, null);
}

新たなメソッドを使ってみる

とりあえず、使ってみることにします。

import java.util.Objects;

public class CheckSize {

    public static void main(String... args) {

        checkIndex();
        checkFromToIndex();
        checkFromIndexSize();

    }

    private static void checkIndex() {
        int a = Objects.checkIndex(2, 8);
        System.out.println("checkIndex:" + a);
    }

    private static void checkFromToIndex() {

        int a = Objects.checkFromToIndex(2, 8, 10);
        System.out.println("checkFromToIndex:" + a);

    }

    private static void checkFromIndexSize() {

        int a = Objects.checkFromIndexSize(2, 8, 10);
        System.out.println("checkFromIndexSize:" + a);

    }

}

実行結果はこうなりました。

checkIndex:2
checkFromToIndex:2
checkFromIndexSize:2

JavaDocにも書かれているように、引数に問題が無ければ一番目の引数をそのまま返すようです。 では、不正な値を渡したらどうなるのでしょう?

private static void checkIndex() {
    int a = Objects.checkIndex(8, 2);
    System.out.println("checkIndex:" + a);
}

こんなエラーを吐きました。

Exception in thread "main" java.lang.IndexOutOfBoundsException: Index 8 out-of-bounds for length 2
    at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
    at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
    at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
    at java.base/java.util.Objects.checkIndex(Objects.java:372)
    at test.CheckSize.checkIndex(CheckSize.java:16)
    at test.CheckSize.main(CheckSize.java:9)

他のメソッドだと以下の通りです。

  • checkFromToIndex()メソッドとそのエラー内容
private static void checkFromToIndex() {
    int a = Objects.checkFromToIndex(8, 1, 10);
    System.out.println("checkFromToIndex:" + a);
}
Exception in thread "main" java.lang.IndexOutOfBoundsException: Range [8, 1) out-of-bounds for length 10
    at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
    at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckFromToIndex(Preconditions.java:76)
    at java.base/jdk.internal.util.Preconditions.checkFromToIndex(Preconditions.java:295)
    at java.base/java.util.Objects.checkFromToIndex(Objects.java:398)
    at test.CheckSize.checkFromToIndex(CheckSize.java:22)
    at test.CheckSize.main(CheckSize.java:10)
  • checkFromIndexSize()メソッドとそのエラー内容
private static void checkFromIndexSize() {
    int a = Objects.checkFromIndexSize(2, 1, 1);
    System.out.println("checkFromIndexSize:" + a);
}
Exception in thread "main" java.lang.IndexOutOfBoundsException: Range [2, 2 + 1) out-of-bounds for length 1
    at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
    at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckFromIndexSize(Preconditions.java:82)
    at java.base/jdk.internal.util.Preconditions.checkFromIndexSize(Preconditions.java:343)
    at java.base/java.util.Objects.checkFromIndexSize(Objects.java:424)
    at test.CheckSize.checkFromIndexSize(CheckSize.java:29)
    at test.CheckSize.main(CheckSize.java:11)

まとめ

通常のロジックで使うにはちょっとエラーメッセージが不親切、という印象です。自分で丁寧に判定ロジックを書いて、状況に合わせてわかりやすいメッセージを作った方がいいかもしれません。

そもそも、使い道がほとんどなさそうです。フレームワーク側で使うかも?くらいでしょうか。何かこんなパターンの時使えるのでは、という閃きがありましたら、教えてください。

10/5追記

Objects.checkIndexメソッドはArrayList.java以外にどこから呼ばれてるのかなとソースコードgrep検索したところ、java.util.ImmutableCollections.javajava.util.AbstractList.java からも呼ばれていました。とはいえ、この二つは開発者は意識しないと思うクラスなので本当に「へー」程度ですね。

#Java9 #String 文字列結合のパフォーマンス向上について

相変わらず謎は解けていない。

www.baeldung.com

www.sitepoint.com

で載っているテストコードを読むと、半角数字の結合結果だけのように読める。
確かに、半角数字だとパフォーマンスはよくなっているのだが、半角英字だとパフォーマンスが悪くなった。

半角英字でパフォーマンスがよくなった、という記事がまだ見つけられていない。

あと、VMオプションは -XX:-CompactStrings でいいようだ。

追記

dzone.com

リンク先のYoutube先で紹介しているテストコードは半角英字だけど、for文でのループはしてないな…。 自分のテストコードのパターンだと遅くなる系だろうか。

2017年9月にリリースされたJava絡みの公式チュートリアルまとめ

これは何の記事?

いつかやってみるかもしれないチュートリアルをまとめておく。

一覧

JUnit 5 User Guide

  • 2017/9/10リリース。
  • PDFへのリンクあり

JUnit 5 User Guide

Java Shell User’s Guide

  • 2017/9/21リリース

Java Platform, Standard Edition Java Shell User’s Guide - Contents

Project Jigsaw: Quick Start Guide

  • 2017/9/21リリース

Project Jigsaw: Quick Start Guide

Java EE Tutorial

  • 2017/9/21リリース。

Java EE Tutorial

半角英字の結合をしたらJava8より遅くなった件の調査【原因不明】 #Java9 #String

これの続編です。 結論から言うと謎が深まっただけです。 tadashi.hatenablog.com

LATIN1/UTF16 の判定が追加になっている、と書いてあるので、判定用の値を取得する coder()メソッドの結果を見てみることにしました。 d.hatena.ne.jp

ソースはこちらです。
※リフレクションを使っています。

https://github.com/suzukitadashi/jmhTest/blob/master/jmhTest/src/main/java/jmhTest/StringTest.java

package jmhTest;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class StringTest {

    private static String[] list = {"a","b","c","d","e","f","g","h","i", "j"};

    public static void main(String... args) {

//        String[] val = {"", "a", "1", "あ"};
//        for(String str : val) {
//            checkCoder(str);
//        }

        test1StringLine();

    }

    private static void checkCoder(String str) {

        System.out.println("------");

        Class<String> c = String.class;
        try {

            Method m = c.getDeclaredMethod("coder");
            m.setAccessible(true);

            byte b = (byte)m.invoke(str);
            System.out.println(str + " coder(): "+b);

            Field f = c.getDeclaredField("coder");
            f.setAccessible(true);
            byte b1 = f.getByte(str);

            System.out.println(str + " coder: "+b1);


        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }


    }


    public static void test1StringLine() {

        int i = 0;
        String str0 = list[i];
        checkCoder(str0);

        i++;
        String str1 = list[i];
        checkCoder(str1);
        i++;
        String str2 = list[i];
        checkCoder(str2);
        i++;
        String str3 = list[i];
        checkCoder(str3);
        i++;
        String str4 = list[i];
        checkCoder(str4);
        i++;
        String str5 = list[i];
        checkCoder(str5);
        i++;
        String str6 = list[i];
        checkCoder(str6);
        i++;
        String str7 = list[i];
        checkCoder(str7);
        i++;
        String str8 = list[i];
        checkCoder(str8);
        i++;
        String str9 = list[i];
        checkCoder(str9);

        String str = str0 + str1 + str2 + str3 + str4 + str5 + str6 + str7 + str8 + str9;

        checkCoder(str);
    }

}

遅くなる理由は、LATIN1で判定して違う、ということでUTF-16の処理になるために処理時間が遅延しているのでは、と推測しました。
さて、結果はというと…

------
a coder(): 0
a coder: 0
------
b coder(): 0
b coder: 0
------
c coder(): 0
c coder: 0
------
d coder(): 0
d coder: 0
------
e coder(): 0
e coder: 0
------
f coder(): 0
f coder: 0
------
g coder(): 0
g coder: 0
------
h coder(): 0
h coder: 0
------
i coder(): 0
i coder: 0
------
j coder(): 0
j coder: 0
------
abcdefghij coder(): 0
abcdefghij coder: 0

coderの値が0ならLATIN1、1ならUTF-16と判定されるロジックなのですが、LATIN1と判定されているようです。
うーん、なんで半角数字同様のパフォーマンスが出てくれないのだろう…?

正式版Java9で文字列の結合の速度を確認する #Java9 #String

これは何?

2017/9/21にJava9が正式にリリースされました。 Java9ではStringのあれこれが変わったと聞いていますが、そんなことはどうでもいいのです。
維持屋にとっては、バージョンアップ後のパフォーマンスがどうなるのか、が重要なのです!!(極論)

前提

これと同じプログラムを使ってテストしました。 qiita.com

@YujiSoftware さんのブログで、VMオプションについて記載されていたのでそれについても試しています。

d.hatena.ne.jp

githubのソースの場所はこちら。 github.com

jmhの起動方法などはこちらにまとめています。 https://github.com/suzukitadashi/jmhTest/blob/master/jmhTest/command.txt

テストした端末のスペックなどは以下の通りです。

  • Windows10 64bit
  • Intel® Core™ i7-2820QM CPU @ 2.30GHz
  • メモリは8GM

結果

注釈

  • スマホからだと見づらいので、パソコンにするか、横にして画面を広げるか、などをお勧めします。
  • Scoreの数字が大きいほど、パフォーマンスがいいと言えます。

半角英字

VM version: JDK 1.8.0_144, VM 25.144-b01

Benchmark                             Mode  Cnt    Score   Error  Units
StringLineHankaku.call1StringLine     thrpt   10  141.099 ± 1.144  ops/s
StringLineHankaku.call2StringConcat   thrpt   10   35.888 ± 0.221  ops/s
StringLineHankaku.call3StringBuffer   thrpt   10   97.689 ± 0.812  ops/s
StringLineHankaku.call4StringBuilder  thrpt   10   98.916 ± 3.052  ops/s

結果全文 https://github.com/suzukitadashi/jmhTest/blob/master/jmhTest/MyBenchmarkStringLineHankakuJava8Result_20170923.txt

VM version: JDK 9-ea, VM 9-ea+134(Early Access版)

Benchmark                             Mode  Cnt    Score   Error  Units
StringLineHankaku.call1StringLine     thrpt   10  90.187 ± 2.961  ops/s
StringLineHankaku.call2StringConcat   thrpt   10  46.822 ± 3.277  ops/s
StringLineHankaku.call3StringBuffer   thrpt   10  68.937 ± 2.796  ops/s
StringLineHankaku.call4StringBuilder  thrpt   10  78.742 ± 2.665  ops/s

結果全文 https://github.com/suzukitadashi/jmhTest/blob/master/jmhTest/MyBenchmarkStringLineHankakuJava9Result.txt

VM version: JDK 9, VM 9+181

VM options: なし

Benchmark                             Mode  Cnt    Score   Error  Units
StringLineHankaku.call1StringLine     thrpt   10  92.795 ±  2.711  ops/s
StringLineHankaku.call2StringConcat   thrpt   10  27.106 ± 17.205  ops/s
StringLineHankaku.call3StringBuffer   thrpt   10  53.108 ± 21.248  ops/s
StringLineHankaku.call4StringBuilder  thrpt   10  62.540 ± 21.275  ops/s

結果全文 https://github.com/suzukitadashi/jmhTest/blob/master/jmhTest/MyBenchmarkStringLineHankakuJava9Result_20170923.txt

VM options: -XX:-CompactStrings -DCompactStringEnabled=false

Benchmark                             Mode  Cnt    Score   Error  Units
StringLineHankaku.call1StringLine     thrpt   10  108.819 ± 4.212  ops/s
StringLineHankaku.call2StringConcat   thrpt   10   50.795 ± 0.952  ops/s
StringLineHankaku.call3StringBuffer   thrpt   10   56.127 ± 0.568  ops/s
StringLineHankaku.call4StringBuilder  thrpt   10  104.129 ± 1.707  ops/s

結果全文 https://github.com/suzukitadashi/jmhTest/blob/master/jmhTest/MyBenchmarkStringLineHankakuJava9Result_20170923_withOption.txt

半角数字

VM version: JDK 1.8.0_144, VM 25.144-b01

Benchmark                            Mode  Cnt    Score    Error  Units
StringLineNumber.call1StringLine     thrpt   10  112.127 ± 34.207  ops/s
StringLineNumber.call2StringConcat   thrpt   10   71.693 ±  0.270  ops/s
StringLineNumber.call3StringBuffer   thrpt   10  103.061 ±  1.590  ops/s
StringLineNumber.call4StringBuilder  thrpt   10   88.149 ± 35.149  ops/s

結果全文

https://github.com/suzukitadashi/jmhTest/blob/master/jmhTest/MyBenchmarkStringLineNumberJava8Result_20170923.txt

VM version: JDK 9-ea, VM 9-ea+134(Early Access版)

Benchmark                            Mode  Cnt    Score    Error  Units
StringLineNumber.call1StringLine     thrpt   10  245.689 ± 13.801  ops/s
StringLineNumber.call2StringConcat   thrpt   10  132.742 ±  9.051  ops/s
StringLineNumber.call3StringBuffer   thrpt   10   49.300 ±  1.349  ops/s
StringLineNumber.call4StringBuilder  thrpt   10   52.594 ±  2.545  ops/s

結果全文

https://github.com/suzukitadashi/jmhTest/blob/master/jmhTest/MyBenchmarkStringLineNumberJava8Result.txt

VM version: JDK 9, VM 9+181

VM options: なし

Benchmark                            Mode  Cnt    Score     Error  Units
StringLineNumber.call1StringLine     thrpt   10  187.399 ± 111.698  ops/s
StringLineNumber.call2StringConcat   thrpt   10  103.961 ±  50.983  ops/s
StringLineNumber.call3StringBuffer   thrpt   10   33.543 ±  21.675  ops/s
StringLineNumber.call4StringBuilder  thrpt   10   51.688 ±   0.346  ops/s

結果全文

https://github.com/suzukitadashi/jmhTest/blob/master/jmhTest/MyBenchmarkStringLineNumberJava9Result_20170923.txt

VM options: -XX:-CompactStrings -DCompactStringEnabled=false

Benchmark                            Mode  Cnt    Score    Error  Units
StringLineNumber.call1StringLine     thrpt   10  238.952 ± 12.086  ops/s
StringLineNumber.call2StringConcat   thrpt   10  107.838 ±  3.610  ops/s
StringLineNumber.call3StringBuffer   thrpt   10  101.667 ± 97.174  ops/s
StringLineNumber.call4StringBuilder  thrpt   10  177.984 ±  3.698  ops/s

結果全文

https://github.com/suzukitadashi/jmhTest/blob/master/jmhTest/MyBenchmarkStringLineNumberJava9Result_20170923_withOption.txt

全角文字

VM version: JDK 1.8.0_144, VM 25.144-b01

Benchmark                             Mode  Cnt    Score   Error  Units
StringLineZenkaku.call1StringLine     thrpt   10  141.133 ± 1.504  ops/s
StringLineZenkaku.call2StringConcat   thrpt   10   36.212 ± 0.202  ops/s
StringLineZenkaku.call3StringBuffer   thrpt   10   97.025 ± 2.155  ops/s
StringLineZenkaku.call4StringBuilder  thrpt   10   99.454 ± 1.509  ops/s

結果全文 https://github.com/suzukitadashi/jmhTest/blob/master/jmhTest/MyBenchmarkStringLineZenkakuJava8Result_20170923.txt

VM version: JDK 9-ea, VM 9-ea+134(Early Access版)

Benchmark                             Mode  Cnt   Score   Error  Units
StringLineZenkaku.call1StringLine     thrpt   10  92.686 ± 0.299  ops/s
StringLineZenkaku.call2StringConcat   thrpt   10  49.554 ± 0.684  ops/s
StringLineZenkaku.call3StringBuffer   thrpt   10  56.950 ± 6.474  ops/s
StringLineZenkaku.call4StringBuilder  thrpt   10  69.917 ± 0.210  ops/s

結果全文 https://github.com/suzukitadashi/jmhTest/blob/master/jmhTest/MyBenchmarkStringLineZenkakuJava9Result.txt

VM version: JDK 9, VM 9+181

VM options: なし

Benchmark                             Mode  Cnt   Score   Error  Units
StringLineZenkaku.call1StringLine     thrpt   10  93.176 ± 1.204  ops/s
StringLineZenkaku.call2StringConcat   thrpt   10  48.488 ± 0.728  ops/s
StringLineZenkaku.call3StringBuffer   thrpt   10  55.984 ± 6.048  ops/s
StringLineZenkaku.call4StringBuilder  thrpt   10  63.517 ± 0.586  ops/s

結果全文

https://github.com/suzukitadashi/jmhTest/blob/master/jmhTest/MyBenchmarkStringLineZenkakuJava9Result_20170923.txt

VM options: -XX:-CompactStrings -DCompactStringEnabled=false

Benchmark                             Mode  Cnt    Score   Error  Units
StringLineZenkaku.call1StringLine     thrpt   10  109.511 ± 1.972  ops/s
StringLineZenkaku.call2StringConcat   thrpt   10   50.061 ± 2.419  ops/s
StringLineZenkaku.call3StringBuffer   thrpt   10   55.549 ± 0.624  ops/s
StringLineZenkaku.call4StringBuilder  thrpt   10  104.124 ± 1.103  ops/s

結果全文

https://github.com/suzukitadashi/jmhTest/blob/master/jmhTest/MyBenchmarkStringLineZenkakuJava9Result_20170923_withOption.txt

まとめ

  • 数値でない場合の結合速度は爆速になるどころか、遅くなっている。

    • @YujiSoftware さんのブログを読む限りでは、半角英字は速くなってもいいはずなのだが…テストプログラムの書き方の問題であろうか?
  • VMオプションを付けると、StringBuilderもStringと同等のパフォーマンスになることがある模様。

    • Java9に挙げた結果、パフォーマンスが遅くなって困るときはVMオプションの付与を検討してもいいかも。[要検証]

お願い

  • 違う結果が出たよ、というのがありましたらテスト方法含めてどこかにまとめたうえで教えてください。勉強しに行きます。