2015/02/06

富山合同勉強会 .NET & Java

1 月 30 日に富山で開催された .NET と Java の合同勉強会 に参加してきました。

毎冬、食べもの駆動で富山にいってますが、.NET の勉強会と合同なのは初めてです。同じ日に、同じ建物でやっているということはあったんですけどね。

しかも、今回は合宿形式で温泉!

でも、櫻庭はそれを気づかずに、富山市内のホテルを予約してしまったのでした ><

参加人数は .NET : Java = 3 : 1 ぐらい。もっと Java 勢にがんばってもらわないと! でも、このぐらいの人数だと、参加者との距離が近いのでツッコミもしやすいし、議論できたりもするのでいいですね。

さて、櫻庭は Project Valhalla と Project Panama の話をしてきました。資料はこちら。

 

 

Project Valhalla と Project Panama は Java SE 10 に入るかもしれない機能です。両方とも VM レベルのパフォーマンス向上などを目的にしたプロジェクトです。

でも、なんでそういう機能が必要なのかというところをまず話しました。

CPU のパフォーマンスが向上しない壁があって、電力 (熱)、ILP (Instruction level parallelism)、メモリアクセス、光速 (配線長) の 4 つです。

特に、メモリアクセスがネックになっていることが多くあります。CPU のパフォーマンス向上に比べると、メモリアクセスのスピードの伸びは低いので、スピードのギャップがどんどん広がっています。

かつて、Brian Goetz が JavaOne のセッションで Memory is the New Disk と言っていたのが、櫻庭にはとても衝撃的でした。

じゃあ、遅いメモリアクセスをしないようにするにはどうするのかというと、キャッシュメモリです。今の CPU はだいたい L1, L2, L3 の 3 段階のキャッシュメモリが備わっています。

L1 へのアクセスは 3 クロックぐらい、L2 が 15 クロックぐらいだそうです。それに対してメインメモリへのアクセスは 200 クロック程度。以下に遅いかが分かります。

つまり、メインメモリにアクセスする状況をなるべく減らすことがキモになります。具体的にはキャッシュミスを如何に減らすかということです。

では、Java ではどうなのという答えの 1 つが、Project Valhalla と Project Panama になるわけです。

Project Valhalla は主に以下の 3 つの仕様について議論されています。

  • ValueType
  • Specialization
  • VarHandle

まず、ValueType ですが、これはプリミティブ型以上、レファレンス型未満とでもいえばいいような型です。C の構造型のようなものとでもいえばいいかもしれません。しかも、イミュタブルに限定されます。

で、ValueType を使う利点は何かというと... たとえば ValueType の配列を考えてみましょう。リファレンス型だと配列にはリファレンスが保持され、そ参照先のオブジェクトはヒープのあちこちに散らばっています。

配列といえば、まとめて扱うことが多いわけですからなるべくまとめてキャッシュにおいておきたいわけですが、オブジェクトがヒープに散らばっているとまとめてキャッシュにおくということが難しくなります。

で、ValueType を使用すると、配列の中に ValueType のフィールドが展開されます。なので、キャッシュにのせやすいわけです。

ValueType の使用法としては、複素数であるとか、long より大きい数値を扱う場合、固定小数点数、タプルなどいろいろあると思います。特にタプルが実現できそうなのはいいですね。

このように ValueType を使用するとプリミティブと同じようにオブジェクトを扱うことができます。たとえば、OptionalInt クラスなんて ValueType で置き換えられますよね。

でも、OptionalInt クラスなんてほんとは使いたくなくて、Optional クラスで十分だと思いませんか。なんでこんなクラスがあるかというと、ジェネリクスの型パラメータとしてプリミティブ型を指定できないからです。

いろいろと過去の経緯や、互換性を重視して今のようにプリミティブ型を使えなくなっています。

これに対して、プリミティブ型を型パラメータとして使えるようにしようというのが、Specialization です。

今のジェネリクスの実装方法はイレージャ方式と呼ばれていますが、これとは違う方法でプリミティブ型を扱えるようにするということです。

これを使えば、IntStream だとか、IntFunction だとか、OptionalInt なんてインタフェース/クラス群は黒歴史として闇に葬り去られそうですw プリミティブ型のラッパークラスもほとんど必要なくなりますね。

まぁ、Specialization にはいろいろと問題も山積みなので、実現するのは大変だと思いますけど。

ちなみに、セッションではほとんど触れなかったのですが、VarHandle は volatile を拡張するためのものです。

 

さて、次の Project Panama です。Project Panama も 3 つの仕様が議論されています。

  • Array 2.0
  • JNR/FFI
  • Data Layout Control

Data Layout Control に関してはあまり公開されている資料がなくて、話せることがないのですが....

Array 2.0 はその名の通り配列をバージョンアップしましょうという仕様です。その中には多次元配列も含まれています。今の Java の 2 次元配列は正確には 2 次元配列ではなくて、単に配列の配列になっています。でも、これだとやっぱりキャッシュにのりにくいんですよね。

それに対して Panama が導入されれば、ちゃんとした 2 次元配列を使うことができるようになります。2 次元配列使いまくりの画像処理なんかはすごい恩恵があるはず。後は、行列計算とか。

JNR はネイティブコードを呼び出すための API です。ネイティブコードを呼び出すには JNI を使ってますけど、これがまた使いにくいし、パフォーマンスもよくない。JNA というのもありますけど、JNA は使いやすいけど、パフォーマンスはイマイチ。

ということで、JRuby の Charles Nutter が中心になって進めているのが JNR (Java Native Runtime) です。

JNR の基板となっているのが、JFFI です。FFI は Foreign Function Interface のことで、一般的な言葉。Java 版の FFI ということで JFFI です。

JNR は JNI と同じようにネイティブコードをコールするだけではなく、Posix 準拠の API を提供していたり、UNIX Socket をそのまま使えたりと、多機能。しかも、パフォーマンスもいいのです。

JNR はもう実装も結構進んでいるので、もしかしたら JNR だけ取り出して Java SE 9 に入れるということもあるかもしれません。

 

ということで、ちょっと未来の Java の話をしてきたわけなのですが、ここらへんの問題って .NET/C# だともう織り込み済みだったりするんですよね。Java が停滞していた時に、C# などはどんどん進化していたので、がんばって Java も追いつかないと。

最後に、参考資料を上げておきます。

0 件のコメント:

コメントを投稿