javaのlambdaの裏事情

25
JavaLambdaの裏事情 ぷろぐぱ ~プログラミング言語のパフォーマンスを考える~ 2013/12/7 きしだ なおき @kis

Upload: -

Post on 10-May-2015

3.442 views

Category:

Technology


1 download

DESCRIPTION

ぷろぐぱ ~プログラミング言語のパフォーマンスを考える~ 2013/12/7 福岡 でのプレゼン資料

TRANSCRIPT

Page 1: JavaのLambdaの裏事情

JavaのLambdaの裏事情

ぷろぐぱ~プログラミング言語のパフォーマンスを考える~

2013/12/7 きしだ なおき@kis

Page 2: JavaのLambdaの裏事情

プログラミング言語が動くまで

● 字句解析– 文字が言語どの構成要素か解析

● 構文解析– 構成要素がどの構文要素か解析

● 実行エンジン– コンパイル言語の場合は実行ファイルを生成

● CPU– 実際に計算を行う

Page 3: JavaのLambdaの裏事情

言語の構文がパフォーマンスに影響

● 動的型付言語は静的型付言語より遅い

● JavaScriptの配列は遅い

– インデックスが連続してなくてもいいため

● (という傾向がある)

Page 4: JavaのLambdaの裏事情

とはいえ

● 動的型付言語も速くしたい● 静的型付言語も便利にしたら遅くなる● みんないろいろ工夫する

Page 5: JavaのLambdaの裏事情

主な戦略

● だいたい難しいことしない● よくある処理が速くなると全体的に速くなる

Page 6: JavaのLambdaの裏事情

ということでJavaの場合

Page 7: JavaのLambdaの裏事情

Java言語とは

● 静的型付● オブジェクト指向

– というかクラス指向

● 事前コンパイル型

– Java VM用バイナリを生成

● Java VMで動く

Page 8: JavaのLambdaの裏事情

実はJava-Javaコンパイラ

● 文字列でのswitch● 匿名クラス

Page 9: JavaのLambdaの裏事情

文字列でのswitch

public static void main(String[] args) { switch(args[0]){ case "a": System.out.println("えー"); break; case "b": System.out.println("びー"); break; } }

public static void main(String[] args) { String str = args[0]; int h = str.hashCode(); int c = 2; switch(h){ case 97: if(str.equals("a")) c = 0; break; case 98: if(str.equals("b")) c = 1; break; } switch(c){ case 0: System.out.println("えー"); break; case 1: System.out.println("びー"); break; } }

Page 10: JavaのLambdaの裏事情

匿名クラス public static void main(String[] args) { List<String> strs = Arrays.asList("a","b","c"); strs.sort(new Comparator<String>() { @Override public int compare(String o1, String o2) { return o2.compareTo(o1); } }); System.out.println(strs); }

public static void main(String[] args) { List<String> strs = Arrays.asList("a","b","c"); strs.sort(new Anonymous$1()); System.out.println(strs); }

private static class Anonymous$1 implements Comparator<String> { @Override public int compare(String o1, String o2) { return o2.compareTo(o1); } }

Page 11: JavaのLambdaの裏事情

Javaの最適化

● Java VMががんばる

– JITなど● ネイティブコードに実行時にコンパイル

● Java VMががんばれるコードをコンパイラが生成する

● Java VMががんばりやすい構文にする

Page 12: JavaのLambdaの裏事情

JVMはJava言語だけのものじゃない

● 動的型

– JRuby

– Clojure

– JavaScript

– Jython● 静的型

– Scala

Page 13: JavaのLambdaの裏事情

ところで圧倒的に動的型!

● Javaがそれなりに使えるので他の静的型言語が使われにくい– より強力な型じゃないと意味がない

● JavaVMにクセがあるので言語仕様で考慮しないと型の威力がでにくい

● ※未検証なので水島さんからツッコミがあると思います

Page 14: JavaのLambdaの裏事情

Java VMのメソッド呼び出し(Java SE 6まで)

● invoke static– staticメソッド

– 常に同じものを呼び出す

– レシーバー(呼び出しオブジェクト)不要

● invoke special– コンストラクタやprivateメソッド

– 常に同じものを呼び出す

– レシーバー必要(以降同様)

● invoke virtual– クラスのインスタンスメソッド

– オブジェクトの型によってメソッドが異なる

● invoke interface– インタフェースのインスタンスメソッド

– オブジェクトの型によってメソッドが異なる

Page 15: JavaのLambdaの裏事情

動的型には不向きだった

● Java VMはJava言語特化

● 動的型言語では呼び出しメソッドがコンパイル時に決めにくい– リフレクションの利用

– Java VMに頼らないメソッド呼び出し

Page 16: JavaのLambdaの裏事情

Java SE 7で導入されたinvoke dynamic

● 動的型言語のため

● 実行時にメソッドの型を決めつつJava VMの最適化もかけやすくする

Page 17: JavaのLambdaの裏事情

invoke dynamicの仕組み

● ブートストラップ– 実際に呼び出すメソッドを探す

– 呼び出すメソッドを指すMethodHandleを生成

– MethodHandleをCallSiteにくるんで返す

● CallSiteにくるまれたMethodHandleが指すメソッドを呼び出す

● 2回目はブートストラップを呼び出さない

● 呼び出し先が変わったらCallSiteが新たなMethodHandleを返す

Page 18: JavaのLambdaの裏事情

ところでJavaにLambdaが来たよ

● (int a, int b) -> { return a + b; }● いろいろ省略できる

– (a, b) -> a + b;

Page 19: JavaのLambdaの裏事情

関数型インタフェース

● 実装すべきメソッドがひとつのインタフェース

– Runnable ( runメソッド)

– Comparator( compareメソッド)

Page 20: JavaのLambdaの裏事情

Lambda式

● Lambdaは関数型インタフェースを実装するクラスのインスタンスを生成するための構文

Comparator<String> comp = new Comparator<String>(){ @Override public int compare(String o1, String o2) { return o2.compareTo(o1); }};

Comparator<String> comp = (o1, o2) -> o2.compareTo(o1);

すっきり!

Page 21: JavaのLambdaの裏事情

Lambdaの裏側

● クラスができていない● メソッドができている

● InvokeDynamic

Page 22: JavaのLambdaの裏事情

なぜ匿名クラスじゃないのか

● クラスができまくる

– Streamなど使うとたくさんクラスができる

– しかもあまり使われない

● いちいちコンストラクタをよびだす

Page 23: JavaのLambdaの裏事情

どのようにInvodeDynamicが使われるか

● ラムダオブジェクトの生成

– LambdaMetaFactory.metafactory– 関数型インタフェースを実装したクラスのインスタンスを生成す

るメソッドが返される● ついでにクラスもこの時点で作ったりする

– そのメソッドを呼び出してラムダオブジェクトを生成

● VMが変わるとより最適化されたインスタンスが生成される– 例:メソッドハンドルをラップする共通クラスのインスタンス

– 例:同じ式には同じインスタンス

Page 24: JavaのLambdaの裏事情

結び

● 言語を実行するためにいろいろがんばってる

● InvokeDynamicは言語要素の最適な実装をあとまわしにできるおもしろい仕組み

● わかると楽しい

Page 25: JavaのLambdaの裏事情

資料

● 「Lambda: A Peek Under The Hood - Brian Goetz」

– http://www.slideshare.net/jaxlondon2012/lambda-a-peek-under-the-hood-brian-goetz

● 「ラムダと invokedynamic の蜜月」

– http://www.slideshare.net/miyakawataku/lambda-meets-invokedynamic

● 「Java 7 invokedynamic の概要」

– http://www.slideshare.net/miyakawataku/java-7-invokedynamic-in-a-nutshell