きしだのはてな このページをアンテナに追加 RSSフィード

2017-11-08(水) Thymeleaf3は2より3倍速く、JDK9では3割遅くなる

[]Thymeleaf3は2より3倍速く、JDK9では3割遅くなる 04:53 Thymeleaf3は2より3倍速く、JDK9では3割遅くなる - きしだのはてな を含むブックマーク

Thymeleaf3がどのくらい2より速くなってるか、あとJDK9のcompact stringは有利に働くかどうか、ベンチマークを取ってみました。

結果として、Thymeleaf3は2より3倍速く、JDK9では遅くなっていて、compact stringは関係なさそうという感じ。

あと、Pebble速い。(というかThymeleaf遅い)


まとめると、こう。単位はops/sで、大きいほど良い。

Thymeleaf cache on no cache
3.0.2 on JDK1.8 16378.948 376.295
3.0.2 on JDK9 11239.364 404.544
2.1.5 on JDK1.8 4621.328 1690.995
2.1.5 on JDK9 4185.943 1505.521
Pebble on JDK1.886571.846
Pebble on JDK9 79746.853

キャッシュなしだとThymeleaf2のほうが速いというのも面白い。

ついでにPebbleも試したけど、いずれにせよThymeleaf遅いな。


JDK1.8の設定はこんな感じ

# VM version: JDK 1.8.0_112, VM 25.112-b15
# VM options: <none>

JDK9の設定はこんな感じ

# VM version: JDK 9.0.1, VM 9.0.1+11
# VM options: <none>

compact stringをはずしてみたらこんな感じ

Thymeleaf cache on no cache
3.0.2 on JDK9 cs 11239.364 404.544
3.0.2 on JDK9 no-cs11502.128 383.660
2.1.5 on JDK9 cs 4185.943 1505.521
2.1.5 on JDK9 no-cs4175.685 1541.948
Pebble on JDK9 cs 79746.853
pebble on JDK9 no-cs87707.230

Thymeleafは差はなさそう。Pebbleはcompact string外した方が速くなってる。


no-csがcompact stringなしで、VMオプションはこんな感じ。

# VM version: JDK 9.0.1, VM 9.0.1+11
# VM options: -XX:-CompactStrings

ついでに、パラメータが英語だけの場合も試してみたけど、compact stringの効果はなさそう。en付のデータ。

Thymeleaf cache on
3.0.2 on JDK9 cs en12934.452
3.0.2 on JDK9 no-cs en12877.672
2.1.5 on JDK9 cs en4286.138
2.1.5 on JDK9 no-cs en4287.446
Pebble on JDK9 cs en83942.007
Pebble on JDK9 no-cs en92066.631

あと、テンプレートキャッシュが効かないと劇的に重いので、サーバーレスでやろうとするならテンプレートもプレコンパイルの仕組みが必要そう。


ソースはこちら

https://github.com/kishida/thymeleaf-bench

2017-11-04(土) OpenJDK/amberをビルドしてパターンマッチングの世界を体験する

[][]OpenJDK/amberをビルドしてパターンマッチングの世界を体験する 08:55 OpenJDK/amberをビルドしてパターンマッチングの世界を体験する - きしだのはてな を含むブックマーク

ほんとはjdk10をビルドしてvarの世界を体験するエントリだったのだけど、ここでバイナリが提供されたので、Amberの話にします。

Project Amberは、Javaにパターンマッチングを導入するプロジェクトです。

varによるローカル変数型推論もAmberの一部だったのだけど、これはjdk10に取り込まれました。jdk10はリポジトリ名で、実際のリリースがJDK10になるかどうかは不明です。


Amberのパターンマッチングがどうなるかというのは、以前ブログにまとめています。

http://d.hatena.ne.jp/nowokay/20170103#1483451037

で、これを試してみるために、ソースをビルドして動かしてみます。今回は、LinuxMacUbuntu on Windowsで試します。


Linux(Ubuntu)でのビルド

ソースをとってきて、ブランチを切り替えて、configureしてmakeというのがビルドの流れです。

ちなみに、OSと必要なライブラリなどあわせて15GBくらいディスクを使うので仮想環境では20GBくらいディスクをとっておく必要があります。ソースとビルド生成物はあわせて6GBくらい。


ビルドにはJDK 9が必要です。

~$ mkdir java
~$ cd java
java$ wget http://download.java.net/java/GA/jdk9/9.0.1/binaries/openjdk-9.0.1_linux-x64_bin.tar.gz
java$ tar zxf openjdk-9.0.1_linux-x64_bin.tar.gz

Mercurialをインストールします。

java$ apt update
java$ apt install mercurial

ソースをとってきて、patternsブランチに切り替えます。cloneは結構時間がかかるので、お風呂とか入るといいと思います。

java$ hg clone http://hg.openjdk.java.net/amber/amber
java$ cd amber
amber$ hg update patterns

今までのビルド手順だとget_source.shを動かしてソースをとってきていましたが、リポジトリ一本化によってcloneだけでよくなったみたいです。amber/amber10-oldなどだと古いパッケージ構成なので、get_source.shが必要のはず。


必要なパッケージをインストールします。

amber$ apt install libx11-dev libxext-dev libxrender-dev libxtst-dev libxt-dev
amber$ apt install lib-cups2-dev  lib-freetype6-dev lib-asound2-dev

では、ビルドを。ビルドにはかなり時間がかかるので、ごはんの支度とかするといいと思います。

amber$ bash configure --with-boot-jdk=~/java/jdk-9.0.1
amber$ make images

configureのときに足りないパッケージはエラーメッセージで教えてくれるので、うまくconfigureできないときは確認してインストールしてください。


さて、ごはんもできたと思うので、おいしくいただきましょう。ついでにJShellも起動してみます。

f:id:nowokay:20171104075418p:image

というか、matches???聞いてないよーーー

matches、キーワードがどうなるかはともかく、かなりキモい仕様になっています。ということで、あとでこのあたりまとめてみます。

ここで試してないけど、ステートメントとしてのswitchもパターンマッチができています。いまのところ、ソースをみる感じswitch式については実装されてない感じです。

※ matchesが使えないときは、patternsブランチに切り替え忘れてないか確認してください。


Macでのビルド

Macでのビルドには、freetypeをインストールしてFreeType関係のオプションを指定する必要があります。

brew install freetype

configureはこんな感じ

bash configure --with-freetype-include=/usr/X11/include/freetype2 --with-freetype-lib=/usr/X11/lib --with-boot-jdk=/Library/Java/JavaVirtualMachines/jdk-9.0.1.jdk/Contents/Home

※ 11/14 追記 XCodeをインストールしておく必要があるっぽい。XCode8が入ってたので大丈夫だったみたい。あと--disable-warnings-as-errorsをつけたほうがいいのかな。

macOSでOpenJDK(amber)ビルドするとエラーになってたのをクリアしてビルドした - Fight the Future


Ubuntu on Windows

Windows用のビルドがやりたかったのだけど、どうもVisual Studio Express 2010が必要ぽくて、インストールできなかったのであきらめた。

Ubuntuとほぼ同じだけど、makeとかが入ってないのでインストールが必要です。

~$ apt install build-essential

あとはUbuntuと同じ手順でいけるはず


プログラミングの基礎 (Computer Science Library)

プログラミングの基礎 (Computer Science Library)

2017-10-12(木) JUnit5で変わるテストの書き方

[] JUnit5で変わるテストの書き方 09:44  JUnit5で変わるテストの書き方 - きしだのはてな を含むブックマーク

JUnit5が案外よさげなので、JUnit5を使うとどんな感じでテストが変わるのか考えてみます。

実際にどこが変わったかとか、使い方自体はいろいろまとめられたブログがあるし、公式ドキュメントも読みやすいのでそちらを。

http://junit.org/junit5/docs/current/user-guide/


メソッドごとのテスト

JUnit5でいいのは、Nestedですね。

いままで、いろんなメソッドを対象にしたテストが入り混じってたと思います。

import org.junit.Before;
import org.junit.Test;
public class PurchaseTest {
    @Before
    public void setup() {
        // 全体のセットアップ
        // purchase()用のセットアップ
        // history()用のセットアップ
    }
    
    @Test
    public void purchase_success() {
    }
    
    @Test
    public void purchase_insufficient() {
    }
    
    @Test
    public void purchase_soldout(){ 
    }
    
    @Test
    public void history() {
    }
    
    @Test
    public void history_nodata() {
    }
}

こんな感じ。hoge_case1みたいなのがたくさん並んで、わかりにくかった。

各メソッド用のセットアップも、全部まとめるか、セットアップ用メソッドを定義して呼び出すか、みたいになっていました。


これをNested使うと、こう。

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
public class PurchaseTest {
    @BeforeEach
    void setup() {
        // 全体のセットアップ
    }
    
    @Nested
    class purchase {
        @BeforeEach
        void setup() {
            // purchase()用のセットアップ
        }
        
        @Test
        void success() {
        }

        @Test
        @DisplayName("金額不足")
        void insufficient() {
        }

        @Test
        void soldout(){ 
        }
    }
    
    @Nested
    class history {
        @BeforeEach
        void setup() {
            // history()用のセットアップ
        }
        
        @Test
        void normal() {
        }

        @Test
        void nodata() {
        }
    }
}

public指定が不要になったのも、地味にありがたい。

メソッドごとのテストをNestedするためのクラス名は、メソッドにあわせて小文字始まりにするのもいいかなと思うけど、IDEとかに警告されそうでもある。


テスト区分

JUnit5からcategoryの代わりにtagが導入されましたが、アノテーションが短くなったところで、いちいちつけるのは面倒。

メタアノテーションが使えるので、これも便利に。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Tag("integration")
@Test
public @interface MySqlIT {
}

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Tag("integration")
@Test
public @interface SpringIT {
}

こんな感じのアノテーションを定義して、


@MySqlIT
void store() {
  // 外部のMySQLにアクセスしちゃうテスト
}

@SpringIT
void login() {
  // よそのSpringを呼び出したりするテスト
}

みたいな感じでテストを書ける。


で、ビルドスクリプトには一括でexcludeできたり。

<configuration>
  <properties>
    <excludeTags>integration</excludeTags>
  </properties>
</configuration>

細分化しすぎると使いにくそうだけど。


パラメタライズテスト

ちょっとずつパラメータ変えたテストを書くのも面倒だったけど、だいぶ楽になります。

junit-jupiter-paramsを別にdependencyに付け加える必要があるので注意。

@ParameterizedTest(name="param test {0}")
@ValueSource(strings = {"one", "two"})
void paramTest(String param) {
    Assertions.assertEquals("one", param);
}

値の生成には、@ValueSourceのほかにも@CsvSourceとか@MethodSourceとかあるので便利そう。


pom

参考までに、これ動かしたpom。

モジュール構成はこんな感じになってます。

f:id:nowokay:20171012093851p:image


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>kis</groupId>
    <artifactId>junit5sample</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
        <junit.jupiter.version>5.0.1</junit.jupiter.version>
        <junit.platform.version>1.0.1</junit.platform.version>
    </properties>

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.7.0</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.19.1</version>
                <dependencies>
                    <dependency>
                        <groupId>org.junit.platform</groupId>
                        <artifactId>junit-platform-surefire-provider</artifactId>
                        <version>${junit.platform.version}</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <dependency>
            <groupId>org.junit.platform</groupId>
            <artifactId>junit-platform-launcher</artifactId>
            <version>${junit.platform.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>${junit.jupiter.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-params</artifactId>
            <version>${junit.jupiter.version}</version>
            <scope>test</scope>
        </dependency>        
    </dependencies>
</project>

2017-10-07(土) 新しいリリースモデルはJavaを使う人 全員要注目だった

[]新しいリリースモデルはJavaを使う人 全員要注目だった 19:05 新しいリリースモデルはJavaを使う人 全員要注目だった - きしだのはてな を含むブックマーク

9月の頭くらいに、Javaのリリースモデルが6ヶ月ごとの短期リリースになるということが発表されてました。

で、「へぇ〜」みたいな感じで見てたのですけど、JavaOneでの話を聞くと、これ結構大変なのかも、ということになってそうなので、ちょっとまとめてみます。


Javaの新しいリリースモデル

公式情報はこちらにまとめられています。(10/4にアップデートされてます)

http://www.oracle.com/technetwork/jp/java/eol-135779-ja.html


ざっくり言えば、6ヶ月ごとに機能リリースを行い、3ヶ月ごとにメンテナンス/セキュリティリリースを行い、基本的にはサポートは次の機能リリースが出るまでだけど、3年ごとに長期サポート付きのLTSリリースを行う、という話で、いままでも話されてました。


けど、これだけだと大事なことが抜けています。

LTSはOracle JDKのみで、オラクルと契約した人だけがダウンロードできるようになる、ということです。

f:id:nowokay:20171006073637j:image

つまり、6ヶ月ごとにOpenJDKがリリースされ、その1ヶ月後と4ヶ月後にメンテナンスアップデートが出て、6ヶ月後に新しい機能を持ったOpenJDKがリリースされて、前のバージョンのOpenJDKはサポート終了。そして3年ごとにLTS付きのOracle JDKがOrackeと契約してる人に提供され、こちらはサポート期間中メンテナンスアップデートが提供される、ということになります。


よく見ると、Oracle JDKが顧客向けになることはOracle Blogsで触れられてますね。

Oracle JDKは、OpenJDKのバイナリがOracle JDKと置き換え可能になると(2018年後半ごろ予定)、主に商用およびサポートの顧客向けになります。

https://orablogs-jp.blogspot.com/2017/09/faster-and-easier-use-and.html


Java 8の公式アップデートは2018/9まで

Java 8は2018/9までで、そしてそこまではJava 9もJava 18.3も短期サポートなので、アップデートするぞーって言ってもなかなか難しそう。


無償で安全に使うなら半年ごとに機能アップデートのOpenJDKを入れていく必要がある

ということになりますね。

ただ、これ結構つらそうで、例えば18.3ではvarが入ると発表されたように、言語仕様がかわるリリースも6ヶ月リリースの中で出てくることになります。

Java VMの仕様が変わるプロジェクトにも、SpecializationやValueTypeが入る「Valhalla」、配列の仕様変更やSIMD命令対応などが入る「Panama」、JITのような実行時ネイティブコンパイルではなく事前ネイティブコンパイルができる「AoT」、コンパイラの再設計でVMにも変更がある「Graal」など、それぞれのプロジェクトが出来た機能を逐次リリースするということになります。

ScalaとかGroovyみたいなJVM言語を作る人たちも対応が大変そう。LTSをターゲットにする、みたいな感じになるのかなという気はするけど。


Java 10は出ない

Java9が最後のメジャーバージョンになる、という話をしていました。

ただ、例えば書籍に「Java 19.3対応!」みたいなことが書いてあっても、いまいちよくわかんないって感じになりそう。OCJとかもどうするんだろう?って思ったけど、これそもそもいまだにSE 6までしかないのか。

まあでも、Java EEのバージョンが、複数独立してバージョンアップされるプロダクトのタグという意味合いであったように、なんらかタグとしてのわかりやすいバージョンは欲しいところです。

ValhallaとAmberが全部入ったらJava10って言って欲しい。


けど、実際どうなるかわからない

これ、実際に世の中がまわっていくモデルじゃない気がするので、今後どうなるかわかんないですね。

冒頭の公式情報も、18.9の公式アップデートがどうなるか書いてないし、Open JDKにLTSがないというのもSafe harbor statement(今から話すのは確定情報じゃないよ、というやつ)付きのJavaOneセッションでの情報だし。


※ 11/13 追記

DEVOXXで、OpenJDKでも3年ごとに3年間のサポートがあるLTSが設定されることや、バージョンは10,11,12となることが発表されています。

https://www.youtube.com/watch?v=x7pkWlost64

2017-10-05(木) JavaOneサンフランシスコ 2017 5日目

[][][]JavaOneサンフランシスコ 2017 5日目 10:39 JavaOneサンフランシスコ 2017 5日目 - きしだのはてな を含むブックマーク

さて、今日は最終日です。

f:id:nowokay:20171006110521j:image


「帰りの会」であるコミュニティキーノートがあったのですが、ちょっと体調がわるかったので、そのあとから。

よこな氏がカンフーマスターだったらしいので見たかったのだけど。


Introduction to Machine Learning with Apache Spark MLlib [CON3165]

SparkとMLlibによる機械学習のセッション

f:id:nowokay:20171006044149j:image


なんか、歌詞からヘビメタかポップかを判別していた

f:id:nowokay:20171006044343j:image


こういったパイプラインが、

f:id:nowokay:20171006044313j:image


Javaコードにそのまま出てますよ、と。

f:id:nowokay:20171006045446j:image


楽しいセッションでした。


Vectors with Values on the JVM [CON4826]

Javaでベクトル計算を行うというセッション。Project Panamaの一部です。

f:id:nowokay:20171006050451j:image


ベクトル計算の場合、ループをアンロールして1ループごとに複数演算を行うということをやります。これをAVX-512などの命令に置き換えるということですね。

f:id:nowokay:20171006052039j:image


Vector APIとしてaddなどのメソッドが用意されています。

f:id:nowokay:20171006052526j:image


パッケージは今のところjdk.incubator.vectorですね。

f:id:nowokay:20171006052730j:image


こんな感じのコードになっています。

f:id:nowokay:20171006053307j:image


128bit以上でハードウェアとの対応ができていません。

f:id:nowokay:20171006054000j:image


で、本来ならValueTypeを使うべきなのだけど、ValhallaとPanamaは別プロジェクトなので、今のところ頼れない、と。

f:id:nowokay:20171006054307j:image


低レベルに対応したAPI呼び出しを、ハードウェア命令にコンパイルするという感じで対応します。

f:id:nowokay:20171006054918j:image


こちらも参照。

http://openjdk.java.net/projects/panama/

https://software.intel.com/en-us/articles/vector-api-developer-program-for-java


How to Make a Project Java 9–Compatible [CON2448]

Java9対応をどうするか、という話。

f:id:nowokay:20171006061740j:image


なんかずっとライブコーディング。

f:id:nowokay:20171006061919j:image

eclipse collectionsでリフレクション使ってるからvmフラグをつけるか新しいバージョンにしましょうね、くらいしか理解できなかった。。。

せめて何に気を付けるべきかというサマリーは1枚資料を作ってほしかった。


Changes to the JDK Release Model [CON8200]

新しいJDKリリースモデルの話。

f:id:nowokay:20171006071158j:image

内容についてはすでにこちらでまとめています。

http://d.hatena.ne.jp/nowokay/20171007#1507284356


6カ月ごとにリリースされて、3年ごとにLTSが出ますよ、という話。

f:id:nowokay:20171006073231j:image


だったのだけど、色が塗り替えられて、LTSはOracleJDKのみと。

f:id:nowokay:20171006073638j:image


あと、Java9が最後のメジャーリリースになる、という話。

f:id:nowokay:20171006074152j:image


今後の動きに要注目でした。

しかし、大事な話なのに、キャパ50人くらいの部屋に35人しか入っていない。気づいてなかったけど、事前にはなくて直前に入ったセッションだったらしい。


カニOne!

最後は日本人参加者が集まってのカニOneです。

f:id:nowokay:20171006114553j:image


今年もお疲れさまでした!

来年は2018/10/28-11/1です。