Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Groovyなう&ふゅーちゃー
それからのGroovy

      GCR 16th
 NTTソフトウェア上原潤二
      2009/1/15
Groovyイン・アクション(GinA)
• 国内初のGroovy解説書(翻訳)
• “バイブル本“
• 対応Groovyバージョン
 –原書はGroovy 1.0ベース
 –サンプルコードをGroovy 1.5.4で動作する
  ように緻密に...
Groovy年表
 2003        2004          2005
   8月        3月     12月 2月
              ▲       ▲     ▲
                        ...
Groovy 1.1と1.5の関係
• 1.1b1, 1.1b2, ・・・, 1.1-RC1,
  ときて1.5
 –Java “5”の機能取り込みと、
  機能が⼤幅アップしたから
 –1.1正式版は存在しない。
 –本資料では、1.1および...
Groovy 1.1=1.5の主な機能
• Java 5対応
  –   アノテーション利⽤
  –   enum(ただし、インナークラスになるenumは×)
  –   可変個数引数
  –   static import
  –   Gen...
Groovy 1.6の主な機能
• ⾔語仕様
    –   マルチ代⼊(多重代⼊)
    –   分岐しててもreturn省略可
    –   AST変換
    –   Groovyでアノテーション定義
• 動的な振る舞いに関するもの
...
ベンチマーク
ベンチマーク!
• The Computer Language
  Benchmarks Game
 –Aka “shootout”
 –マイクロベンチマーク
• 抜粋して実施
その前に
• 速度にこだわるべき?
 –マシンも速くなってるし
 –Groovyであることで遅いなら、
  ボトルネックをJavaで書き直せばよい
  それはものすごく簡単
• 処理系速度は体感速度に対して⽀配的
  とは限らない
 –ライブラ...
Groovy 1.1beta3を1とした速度⽐
Groovy 1.5.6を1とした速度⽐
感想(感覚的なものです)
• Groovy 1.6でメソッドコールが爆
  速に(理由は後述)
• つってもJRubyと同等(かやや上)
• JVM上の⾔語の共通の特徴として
 –起動は遅いっすよ
 –メモリは⽐較的⾷うっすよ
From 1.1・1.5
エルビス演算⼦(Elvis Operator)
• 三項演算⼦
 A?B:C
 は次と等価
 if (A) { B } else { C }
• エルビス演算⼦                  ※GCCの独自拡張に由来

 A ?: B
 は...
エルビス演算⼦(Elvis Operator)
ジョイントコンパイラ
• GroovyとJavaコードが相互依存してい
  てもコンパイル可能に
   class A {
     B b;
   }

   class B extends A {}
• 内部では、Groovyクラスのスタブ...
ExpandoMetaClass (EMC)
• プロパティにクロージャを代⼊する
  とメソッドの様に扱える
 String.metaclass.hello = { println “hello”+delegate }
 “world”.he...
From 1.6
Call Siteキャッシュ,Call Site最適化
• 性能向上の主因
 –「メソッドコールが遅い」←Groovyの遅
  さは⼤半これで説明。
• 動的メソッド呼び出しに先⽴つメソッ
  ド探索をキャッシュ
 –動的⾔語で効果が⼤
 –J...
動的メソッド呼び出し概念フロー

呼び出し側クラス                      GroovyクラスX

x = new X()                    Class X {
x.foo()
              ...
動的メソッド呼び出し概念フロー

呼び出し側クラス                   GroovyクラスX

x = new X()                Class X {
x.foo()
               メソッド探索...
問題はメソッド探索のコスト
• 探索時に以下の判定を⾏う必要がある
 –Pojo/Pogoのメソッド?
 –メタクラス定義メソッド?
  •クラスごとのメタクラス?
  •インスタンスごとのメタクラス?
 –プロパティ参照か?         ...
Call Site Cache (1回⽬)

  呼び出し側クラス                           GroovyクラスX

  x = new X()                        Class X {
  x...
Call Site Cache (2回⽬)
  呼び出し側クラス                          GroovyクラスX

 x = new X()                        Class X {
 x.foo...
Call Site最適化まとめ
• (1)メソッド探索コストを2回⽬以降削減
• (2)JITによるインライン展開の道を開く
 – マシン語レベルでほんとに展開されているか私
   は確認してません(Open JDKで確認可)がほんと
   な...
Grape:依存クラス⾃動ダウンロード
• Maven/RubyGemsみたいなリポジト
  リベースモジュール管理
 – Apache Ivyベース
 – Groovyレベルで標準基本機能として実現
 – 必要なクラス/Jarを実⾏時にも取っ...
Grape使い⽅
• アノテーション
  import org.junit.*
  @Grab(group = 'junit', module='junit', version='*')
  public class GrapeTestSub ...
JavaインスタンスごとのMetaClass
• 例:
 s = “xxx”;
 s.metaClass.a = { println quot;hogequot;}
 s.a()
 // hogeが出⼒
 – Groovyならもともと可能
 –...
AST変換
• AST …抽象構⽂⽊
 – コンパイル中にコンパイラ内で作られる
   中間データ構造
• AST変換
 – 指定したアノテーションが与える規則に従って、
   コンパイル時にASTを変換することで、⾔語機能
   を加⼯・追加...
AST変換の例
   アノテーション                      説明
@Bindable/@Vetoable   プロパティの更新伝播(java.beans.
                      PropertyChan...
AST変換: @Singleton
@Singleton class Foo {
 def hello() { println quot;helloquot; }
}
Foo.instance.hello() // シングルトン参照
a = n...
AST変換: @Immutable
@Immutable final class Foo {
 String x, y
}
a = new Foo(quot;aquot;,quot;bquot;)
a.x = “hoge”           ...
AST変換: @Delegate
import java.util.concurrent.locks.*
class LockableMap {
  @Delegate private Map map = [:]
  @Delegate pri...
AST変換: @Lazy
class LazyTest {
  @Lazy List s1 ={println quot;s1 initializingquot;; [1,2,3] }();
  List s2 = {println quot;...
AST変換: @Category/@Mixin
interface Mixed {
}

@Category(Mixed) class CatClass {
  def hello() { println quot;helloquot; }
}...
動的なMixinメソッド呼び出し

String.mixin Date
assert quot;aquot;.getTime() == 1231768545451




                                From...
整理:さまざまな機能注⼊の⽅法
          名称             注⼊単位         注⼊タイミング          対象
メソッドを書く                メソッド          コンパイル時     ...
マルチ代⼊(多重代⼊)
def (a, b) = [1,2]

def (int i, String j) = [1, 'Groovy']

def a, b
(a, b) = func()

• 要素が余ったら捨て、⾜りなかったら
  nul...
分岐しててもreturn省略可
def even(x) {
  if (x % 2 == 0) { true } else { false }
}
assert even(2) == true
assert even(1) == false

...
EMC DSL
• 逐次プロパティに代⼊するのではなく
  ⼀気に定義する。
String.metaClass.define {
  foo { s-> println s + delegate }
  bar { println “hello...
まとめ
まとめ: Groovyの⽬指すもの
• Java 7がしょぼくなった今、Groovyは
  ⾔語機能拡張のメルティングポット
 –Java 7のクロージャ(案)は、⼿ひどく複雑
  そうだったので、正直ほっとしている。
• “Java is C...
参考文献
• http://glaforge.free.fr/weblog/index.php?itemid=241
• http://www.nabble.com/DGM-and-GDoc-
  to14985262.html#a149852...
Upcoming SlideShare
Loading in …5
×

Groovy Now And Future

3,508 views

Published on

Groovy new fetures
Call site optimization,
AST Translation,
mixin, etc.

Published in: Technology
  • [url=www.rgpipefitting.com]很漂亮[/url]啊http://www.rgpipefitting.com
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • it is very good
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

Groovy Now And Future

  1. 1. Groovyなう&ふゅーちゃー それからのGroovy GCR 16th NTTソフトウェア上原潤二 2009/1/15
  2. 2. Groovyイン・アクション(GinA) • 国内初のGroovy解説書(翻訳) • “バイブル本“ • 対応Groovyバージョン –原書はGroovy 1.0ベース –サンプルコードをGroovy 1.5.4で動作する ように緻密に修正。 –Groovy 1.0より後に実装された機能につい ては基本的には追記しない。 ので本発表ではそこを説明します
  3. 3. Groovy年表 2003 2004 2005 8月 3月 12月 2月 ▲ ▲ ▲ 本日の対象 1.0b4 1.0b8 1.0b10 JSR化 JSR EA 2006 2007 2008 1.1b1 7月 2月 4月 12月 2月 12月 ▲ ▲ ▲ ▲ ▲ ▲ 1.0 JSR-6 1.0 1.1b2 1.5.0 1.5.4 1.5.7 1.6-rc1 GinA本対象 Grails 0.5.6 Grails 1.0 1.1b2
  4. 4. Groovy 1.1と1.5の関係 • 1.1b1, 1.1b2, ・・・, 1.1-RC1, ときて1.5 –Java “5”の機能取り込みと、 機能が⼤幅アップしたから –1.1正式版は存在しない。 –本資料では、1.1および1.5の新機能を From 1.1・1.5 のマークで表⽰ –ちなみに1.6機能は From 1.6 で。
  5. 5. Groovy 1.1=1.5の主な機能 • Java 5対応 – アノテーション利⽤ – enum(ただし、インナークラスになるenumは×) – 可変個数引数 – static import – Generics – 共変の戻り値 • ⾔語仕様 – エルビス演算⼦ – for(;;)形式ループ – 名前付き引数で関数呼び出しの括弧省略 • ジョイントコンパイラ • Expando Meta Class (EMC) From 1.1・1.5 • 性能向上,bugfix,改良,etc,etc,
  6. 6. Groovy 1.6の主な機能 • ⾔語仕様 – マルチ代⼊(多重代⼊) – 分岐しててもreturn省略可 – AST変換 – Groovyでアノテーション定義 • 動的な振る舞いに関するもの – JavaインスタンスごとのMetaClass – EMC DSL – 実⾏時Mixin • ライブラリ: Swing Builderの改善 • ツール: Grape • 性能向上 • bugfix,改良,etc,etc From 1.6
  7. 7. ベンチマーク
  8. 8. ベンチマーク! • The Computer Language Benchmarks Game –Aka “shootout” –マイクロベンチマーク • 抜粋して実施
  9. 9. その前に • 速度にこだわるべき? –マシンも速くなってるし –Groovyであることで遅いなら、 ボトルネックをJavaで書き直せばよい それはものすごく簡単 • 処理系速度は体感速度に対して⽀配的 とは限らない –ライブラリやIOの性能が⽀配的な場合も • でも –Groovy同⼠なら⾯⽩かろう
  10. 10. Groovy 1.1beta3を1とした速度⽐
  11. 11. Groovy 1.5.6を1とした速度⽐
  12. 12. 感想(感覚的なものです) • Groovy 1.6でメソッドコールが爆 速に(理由は後述) • つってもJRubyと同等(かやや上) • JVM上の⾔語の共通の特徴として –起動は遅いっすよ –メモリは⽐較的⾷うっすよ
  13. 13. From 1.1・1.5
  14. 14. エルビス演算⼦(Elvis Operator) • 三項演算⼦ A?B:C は次と等価 if (A) { B } else { C } • エルビス演算⼦ ※GCCの独自拡張に由来 A ?: B は次と等価 if (A) { A } else { B } From 1.1・1.5
  15. 15. エルビス演算⼦(Elvis Operator)
  16. 16. ジョイントコンパイラ • GroovyとJavaコードが相互依存してい てもコンパイル可能に class A { B b; } class B extends A {} • 内部では、Groovyクラスのスタブ(メ ソッド本体を削除したもの)を⽣成して からJavaコンパイラを起動する • groovycの-jオプションで実⾏ From 1.1・1.5
  17. 17. ExpandoMetaClass (EMC) • プロパティにクロージャを代⼊する とメソッドの様に扱える String.metaclass.hello = { println “hello”+delegate } “world”.hello() // helloworldが出⼒ • 簡便な動的メソッド定義。 • prototypeと同様だが、Groovyでは クラスベースOOPと⼆本⽴て。 EMCは後付け。 From 1.1・1.5
  18. 18. From 1.6
  19. 19. Call Siteキャッシュ,Call Site最適化 • 性能向上の主因 –「メソッドコールが遅い」←Groovyの遅 さは⼤半これで説明。 • 動的メソッド呼び出しに先⽴つメソッ ド探索をキャッシュ –動的⾔語で効果が⼤ –JRubyが先達 –アイデア⾃体は古くからある • JVM上で極めて有効(後述) From 1.6
  20. 20. 動的メソッド呼び出し概念フロー 呼び出し側クラス GroovyクラスX x = new X() Class X { x.foo() メソッド探索 def foo() { Pogo呼び出し } Pogo …Plain Old Groovy Object
  21. 21. 動的メソッド呼び出し概念フロー 呼び出し側クラス GroovyクラスX x = new X() Class X { x.foo() メソッド探索 メタクラスのメソッド } の呼び出し Xのメタクラス ‘foo’ = { }
  22. 22. 問題はメソッド探索のコスト • 探索時に以下の判定を⾏う必要がある –Pojo/Pogoのメソッド? –メタクラス定義メソッド? •クラスごとのメタクラス? •インスタンスごとのメタクラス? –プロパティ参照か? 明ら –コンストラクタ呼び出しか? かに –インタセプト可能か? 重い –Staticかどうか? :
  23. 23. Call Site Cache (1回⽬) 呼び出し側クラス GroovyクラスX x = new X() Class X { x.foo() メソッド探索 PogoMetaClassSiteの } インスタンスを保存 Xのメタクラス CallSite ‘foo’ = { } ※CallSiteはSoftReferenceで保持されるので メモリがなくなってきたら解放される
  24. 24. Call Site Cache (2回⽬) 呼び出し側クラス GroovyクラスX x = new X() Class X { x.foo() 保存された } PogoMetaClassSiteの インスタンスをcall() Xのメタクラス CallSite ‘foo’ = { } ※実際には呼び出しが複数あるので配列CallSiteArrayで保持 ※意味が動的に変わったらCallSiteのインスタンスを差し替える (自分で自分を置き換える。コード的にはこれがやや面白い)
  25. 25. Call Site最適化まとめ • (1)メソッド探索コストを2回⽬以降削減 • (2)JITによるインライン展開の道を開く – マシン語レベルでほんとに展開されているか私 は確認してません(Open JDKで確認可)がほんと なら⾮常に効果が⾼い(連鎖的展開を導く) – インライン展開に関してHotSpotは極めて強⼒ • アグレッシブにやって状況変わったら Deoptimization(最適化戻し) • (3)特定のメタメソッドについて、⾃分専⽤ の速いCall Siteを⽣成 – DefaultGroovyMethod#additionals参照
  26. 26. Grape:依存クラス⾃動ダウンロード • Maven/RubyGemsみたいなリポジト リベースモジュール管理 – Apache Ivyベース – Groovyレベルで標準基本機能として実現 – 必要なクラス/Jarを実⾏時にも取ってこれる – 依存関係があれば連鎖的にJarを取ってくる – Grails Pluginのような、実⾏時モジュール 機構は含まない • 効⽤: Groovyスクリプト配布が容易に From 1.6
  27. 27. Grape使い⽅ • アノテーション import org.junit.* @Grab(group = 'junit', module='junit', version='*') public class GrapeTestSub { String testMethod() { Assert.class.name } } • メソッド呼び出し Grape.grab(group:'org.jidesoft', module:'jide- oss', version:'[2.2.0,)') • ʼgrapeʼコマンド From 1.6
  28. 28. JavaインスタンスごとのMetaClass • 例: s = “xxx”; s.metaClass.a = { println quot;hogequot;} s.a() // hogeが出⼒ – Groovyならもともと可能 – 「JavaクラスごとのMetaClass」は元々あった • 参考:クラスごとのMetaClass String.metaClass.x={println “hoge” } “abc”.x() // hogeが出⼒ From 1.6
  29. 29. AST変換 • AST …抽象構⽂⽊ – コンパイル中にコンパイラ内で作られる 中間データ構造 • AST変換 – 指定したアノテーションが与える規則に従って、 コンパイル時にASTを変換することで、⾔語機能 を加⼯・追加する – デザインパターン指向プログラミング – コンパイラソースを修正せずに⾔語機能追加。 – 定義は結構難しそう(Visitorで) – 利⽤は簡単 From 1.6
  30. 30. AST変換の例 アノテーション 説明 @Bindable/@Vetoable プロパティの更新伝播(java.beans. PropertyChangeSupport使⽤) @Singleton クラスをシングルトンに変換 @Immutable インスタンス⽣成後の変更を禁⽌ @Delegate 委譲(delegation)パターン を透過的に実現 @Lazy プロパティの怠惰(Lazily)な初期化 @Category / @Mixin カテゴリのメソッドをコンパ イル時にmixinする @Newify newなしで「Integer(5)」と書けばイ ンスタンスが⽣成。(未実装?) packageスコープの指定。フィールド @PackageScope については動いているようだがクラス については?
  31. 31. AST変換: @Singleton @Singleton class Foo { def hello() { println quot;helloquot; } } Foo.instance.hello() // シングルトン参照 a = new Foo() // newでインスタンス⽣成不可 ERROR java.lang.RuntimeException: Can't instantiate singleton Foo. Use Foo.instance
  32. 32. AST変換: @Immutable @Immutable final class Foo { String x, y } a = new Foo(quot;aquot;,quot;bquot;) a.x = “hoge” 値の変更 ERROR groovy.lang.ReadOnlyPropertyExcep tion: Cannot set readonly property: x
  33. 33. AST変換: @Delegate import java.util.concurrent.locks.* class LockableMap { @Delegate private Map map = [:] @Delegate private Lock lock = new ReentrantLock () } res = new LockableMap() res.lock () Lockとして振舞う try { res.a = 0 Mapとしても振舞う } finally { res.unlock () ※MapとLockをimplementsもする }
  34. 34. AST変換: @Lazy class LazyTest { @Lazy List s1 ={println quot;s1 initializingquot;; [1,2,3] }(); List s2 = {println quot;s2 initializingquot;; [4,5,6] }(); } x = new LazyTest() // s2 initializing s1の初期化は遅延される println x.s1 s1への参照で初期化実⾏ // s1 initializing // [1, 2, 3]が出⼒される println x.s2 // [4, 5, 6]が出⼒される
  35. 35. AST変換: @Category/@Mixin interface Mixed { } @Category(Mixed) class CatClass { def hello() { println quot;helloquot; } } @Mixin(CatClass) class MyClass implements Mixed { } x = new MyClass() x.hello() ※interface Mixedの意義が不明。なんらかの処理上のマーカー?
  36. 36. 動的なMixinメソッド呼び出し String.mixin Date assert quot;aquot;.getTime() == 1231768545451 From 1.6
  37. 37. 整理:さまざまな機能注⼊の⽅法 名称 注⼊単位 注⼊タイミング 対象 メソッドを書く メソッド コンパイル時 クラス 継承 メソッド群 コンパイル時 クラス Category/use staticメソッド群 実⾏時(use⽂実⾏時) クラス DefaultGroovyMethods staticメソッド群 Groovy処理系のコンパイ クラス(Java) .java(DGM) ル時 MOP(invokeMethod,me メソッド呼び出し オーバーライドはコンパ クラス thodMissing) に対応する処理 イル時に⾏われるが、処 理内容は実⾏時に決定可 インターセプタ メソッド呼び出し 実⾏時 インスタンス の前後の処理 Mixinメソッド呼び出し メソッド群 実⾏時 クラス 1.6 Mixinアノテーション メソッド群 コンパイル時 クラス Delegateアノテーション メソッド群? コンパイル時 クラス EMC DSL クロージャ群 実⾏時 クラス/イン スタンス ExpandoMetaClass(EM クロージャ 実⾏時 クラス/イン 1.1 C) スタンス 1.5 Expando クロージャ 実⾏時 インスタンス
  38. 38. マルチ代⼊(多重代⼊) def (a, b) = [1,2] def (int i, String j) = [1, 'Groovy'] def a, b (a, b) = func() • 要素が余ったら捨て、⾜りなかったら nullで補填 From 1.6
  39. 39. 分岐しててもreturn省略可 def even(x) { if (x % 2 == 0) { true } else { false } } assert even(2) == true assert even(1) == false • ちなみにwhile⽂の最終評価式は値にはなら ないようだ From 1.6
  40. 40. EMC DSL • 逐次プロパティに代⼊するのではなく ⼀気に定義する。 String.metaClass.define { foo { s-> println s + delegate } bar { println “hello” } } “world”.foo(“hai”) // haiworldが出⼒ “abc”.bar() // helloが出⼒ ※効用: 逐次代入だと、途中で未完成状態のクラスが生じるから? From 1.6
  41. 41. まとめ
  42. 42. まとめ: Groovyの⽬指すもの • Java 7がしょぼくなった今、Groovyは ⾔語機能拡張のメルティングポット –Java 7のクロージャ(案)は、⼿ひどく複雑 そうだったので、正直ほっとしている。 • “Java is COBOL”?そうじゃあない。 “Java is C”なんだ。 –ポイントは「住み分け」 • Groovyは、JVM上にクラスをローディ ングするための別記法。 • 「Java+Groovy」は2つで⼀つの技術
  43. 43. 参考文献 • http://glaforge.free.fr/weblog/index.php?itemid=241 • http://www.nabble.com/DGM-and-GDoc- to14985262.html#a14985262 • http://blog.headius.com/2008/05/power-of-jvm.html • http://glaforge.free.fr/weblog/index.php?itemid=99 • http://glaforge.free.fr/weblog/index.php?itemid=256 • http://www.infoq.com/jp/articles/groovy-1.5-new‘ • http://shootout.alioth.debian.org/ • http://d.hatena.ne.jp/masanobuimai/20081224/1230123639 • http://docs.codehaus.org/display/GROOVY/Grape • http://docs.codehaus.org/pages/viewrecentblogposts.action?k ey=GROOVY • http://shemnon.com/speling/2008/04/bindable-observable- properties.html

×