javaone tokyo jvm言語bof ベンチマーク jruby

24
JVM言語BoF プログラミング テーマ: 赤黒木ベンチマーク (JRuby担当) 日本JRubyユーザ会 中村浩士 @nahi [email protected] https://github.com/nahi

Upload: hiroshi-nakamura

Post on 12-Jun-2015

1.529 views

Category:

Documents


1 download

DESCRIPTION

JavaOne Tokyo 2012 JVM言語BOF プログラミング大会のベンチマークテーマ、JRuby発表。

TRANSCRIPT

Page 1: JavaOne Tokyo JVM言語BOF ベンチマーク JRuby

JVM言語BoF プログラミング

テーマ: 赤黒木ベンチマーク

(JRuby担当)

日本JRubyユーザ会 中村浩士@nahi [email protected]://github.com/nahi

Page 2: JavaOne Tokyo JVM言語BOF ベンチマーク JRuby

赤黒木ベンチマークのポイント

JVM言語 × ロジックヘビーなプログラム

速度性能?コードの読み易さ?

赤黒木は最近雑誌で紹介され、馴染みがあった Groovy、Scala、JRubyで比較

さらにJava、Groovy++、CRubyも

Page 3: JavaOne Tokyo JVM言語BOF ベンチマーク JRuby

赤黒木とは

データ構造の一種: 平衡二分木(バランス木)他の平衡二分木に比べ「ほどほど」のバランスデータ追加・削除後のバランス調整が楽

B

A D

C E

F

D

B E

C FA

AVL木 赤黒木

Page 4: JavaOne Tokyo JVM言語BOF ベンチマーク JRuby

レギュレーション: 連想配列RBTreeMap

詳細: http://bit.ly/RedBlackTreeBenchmark RBTreeMapは以下のAPIを持つ。

put(String key, String value) => Objectkeyに対してvalueを結びつける。keyにはStringの

同値性、順序性を期待できるものとする。get(String key) => String

keyに対して割り当てられている値を返す。

型は各言語におけるString相当の型を扱えればよい。

マルチスレッドからアクセスされた場合の挙動は未定義。

Page 5: JavaOne Tokyo JVM言語BOF ベンチマーク JRuby

レギュレーション: ベンチマーク取得方法

RBTreeMapをインスタンス化する。

用意したファイルを開き、全てを読み終わるまで以下を繰り返す。

ファイルから1行読み込み、key、value文字列を取り出す。

RBTreeMap#put(key, value)を呼ぶ。

再度同じファイルを開き、全てを読み終わるまで以下を繰り返す。

ファイルから1行読み込み、key、value文字列を取り出す。

RBTreeMap#get(key)がvalueと一致することを確認する。

上記全体の経過時間を5回計測し、中間3値の平均を取る。

Page 6: JavaOne Tokyo JVM言語BOF ベンチマーク JRuby

入力データ

aahenbi|jtbi,aahenbi|jtbi,1aabpta||_s`f,aabpta||_s`f,1aaosi^t`sgd`,aaosi^t`sgd`,2aakzh_nisbdi,aakzh_nisbdi,2aamppbpz|b|l,aamppbpz|b|l,2aaleu_dhypqh,aaleu_dhypqh,2aadlx`{tlvqs,aadlx`{tlvqs,2aabta__zuda|,aabta__zuda|,3aaiga^hhtvh`,aaiga^hhtvh`,3aacczbs^kgfl,aacczbs^kgfl,3aacnpac_luj^,aacnpac_luj^,3aakre^v|gmpy,aakre^v|gmpy,3aamfb`_we|ap,aamfb`_we|ap,3aaexv`mwfvyw,aaexv`mwfvyw,3aaalj^ufcaza,aaalj^ufcaza,3aaccnb_jxhhn,aaccnb_jxhhn,3aagwmb`e^suk,aagwmb`e^suk,3aafxpbwypsye,aafxpbwypsye,3aakjlbqzvgpv,aakjlbqzvgpv,4...

改行"\n"、区切り","、エスケープなし

簡易CSV。key、value、木の高さの3列。---key,value,1[\n]key2,value2,1[\n]...keyn,valuen,11[\n][EOF]----

実際に利用したデータは

key==value、またkeyの

hashCodeが全て同じ値。

Page 7: JavaOne Tokyo JVM言語BOF ベンチマーク JRuby

ベンチマーク環境

CPU: Intel(R) Core(TM) i5 CPU M 540 @ 2.53GHz × 4Memory: 2.25GBOS: Ubuntu 11.10 64bit(VMware workstationで動作、ホストはWindows 7 64bit) Java: Java SE 7u3 Linux x64java version "1.7.0_03"Java(TM) SE Runtime Environment (build 1.7.0_03-b04)

Java HotSpot(TM) 64-Bit Server VM (build 22.1-b02, mixed mode)

Page 8: JavaOne Tokyo JVM言語BOF ベンチマーク JRuby

JRuby版ソースコード解説

赤黒木ベンチマーク

https://github.com/nahi/javaone2012-benchmark

Page 9: JavaOne Tokyo JVM言語BOF ベンチマーク JRuby

class RBTreeMap def initialize def get(key) def put(key, value) class RBTree attr_reader :key, :value attr_accessor :color, :left, :right def initialize(key, value) def make_as_root def empty? def red? def black? def retrieve(key) def insert(key, value) class EmptyTree < RBTree def initialize def empty? def insert(key, value) end protected def insert_rotate_left def insert_rotate_right def insert_color_flip def swap_color(other) private def rotate_left def rotate_right def color_flip endend

ソースコード全体概略(全メソッド抽出)定義を含め全195行

Page 10: JavaOne Tokyo JVM言語BOF ベンチマーク JRuby

class RBTreeMap def initialize def get(key) def put(key, value) class RBTree attr_reader :key, :value attr_accessor :color, :left, :right def initialize(key, value) def make_as_root def empty? def red? def black? def retrieve(key) def insert(key, value) class EmptyTree < RBTree def initialize def empty? def insert(key, value) end protected def insert_rotate_left def insert_rotate_right def insert_color_flip def swap_color(other) private def rotate_left def rotate_right def color_flip endend

RBTreeMapのメソッド

Page 11: JavaOne Tokyo JVM言語BOF ベンチマーク JRuby

class RBTreeMap def initialize def get(key) def put(key, value) class RBTree attr_reader :key, :value attr_accessor :color, :left, :right def initialize(key, value) def make_as_root def empty? def red? def black? def retrieve(key) def insert(key, value) class EmptyTree < RBTree def initialize def empty? def insert(key, value) end protected def insert_rotate_left def insert_rotate_right def insert_color_flip def swap_color(other) private def rotate_left def rotate_right def color_flip endend

RBTreeMapが内部利用するRBTreeの定義

Page 12: JavaOne Tokyo JVM言語BOF ベンチマーク JRuby

class RBTreeMap def initialize def get(key) def put(key, value) class RBTree attr_reader :key, :value attr_accessor :color, :left, :right def initialize(key, value) def make_as_root def empty? def red? def black? def retrieve(key) def insert(key, value) class EmptyTree < RBTree def initialize def empty? def insert(key, value) end protected def insert_rotate_left def insert_rotate_right def insert_color_flip def swap_color(other) private def rotate_left def rotate_right def color_flip endend

木の末端(葉)にある「空」の定義

Page 13: JavaOne Tokyo JVM言語BOF ベンチマーク JRuby

class RBTreeMap def initialize def get(key) def put(key, value) class RBTree attr_reader :key, :value attr_accessor :color, :left, :right def initialize(key, value) def make_as_root def empty? def red? def black? def retrieve(key) def insert(key, value) class EmptyTree < RBTree def initialize def empty? def insert(key, value) end protected def insert_rotate_left def insert_rotate_right def insert_color_flip def swap_color(other) private def rotate_left def rotate_right def color_flip endend

protected、privateの意味がJavaと異なるのに注意

Page 14: JavaOne Tokyo JVM言語BOF ベンチマーク JRuby

class RBTree attr_reader :key, :value attr_accessor :color, :left, :right

def initialize(key, value) @key, @value = key, value @left = @right = EMPTY # new node is added as RED @color = :RED end

def make_as_root @color = :BLACK end

def empty? false end

def red? @color == :RED end

def black? @color == :BLACK end

getのみ、およびget/setの簡易定義

Page 15: JavaOne Tokyo JVM言語BOF ベンチマーク JRuby

class RBTree attr_reader :key, :value attr_accessor :color, :left, :right

def initialize(key, value) @key, @value = key, value @left = @right = EMPTY # new node is added as RED @color = :RED end

def make_as_root @color = :BLACK end

def empty? false end

def red? @color == :RED end

def black? @color == :BLACK end

メソッド名末尾に?が使える

Page 16: JavaOne Tokyo JVM言語BOF ベンチマーク JRuby

# returns new tree def insert(key, value) case key <=> @key when -1 @left = @left.insert(key,value) when 0 @value = value when 1 @[email protected](key,value) end # Rebalance of LL red-black trees insert_rotate_left. insert_rotate_right. insert_color_flip end

# returns value def retrieve(key) ptr = self while !ptr.empty? case key <=> ptr.key when -1 ptr = ptr.left when 0 return ptr.value when 1 ptr = ptr.right end end nil end

挿入は再帰で実装

Page 17: JavaOne Tokyo JVM言語BOF ベンチマーク JRuby

# returns new tree def insert(key, value) case key <=> @key when -1 @left = @left.insert(key,value) when 0 @value = value when 1 @[email protected](key,value) end # Rebalance of LL red-black trees insert_rotate_left. insert_rotate_right. insert_color_flip end

# returns value def retrieve(key) ptr = self while !ptr.empty? case key <=> ptr.key when -1 ptr = ptr.left when 0 return ptr.value when 1 ptr = ptr.right end end nil end

参照はループで実装

Page 18: JavaOne Tokyo JVM言語BOF ベンチマーク JRuby

class EmptyTree < RBTree def initialize @value = nil @color = :BLACK end

def empty? true end

# returns new_root def insert(key, value) RBTree.new(key, value) end

def height 0 end end private_constant :EmptyTree EMPTY = EmptyTree.new.freeze

末端への挿入により木が大きくなる

Page 19: JavaOne Tokyo JVM言語BOF ベンチマーク JRuby

# Do roate_left after insert if needed def insert_rotate_left if @left.black? and @right.red? rotate_left else self end end

# Do rotate_right after insert if needed def insert_rotate_right if @left.red? and @left.left.red? rotate_right else self end end

# Do color_flip after insert if needed def insert_color_flip if @left.red? and @right.red? color_flip else self end end

def swap_color(other) @color, other.color = other.color, @color end

リズムよく、山の形の定義が連なる

Page 20: JavaOne Tokyo JVM言語BOF ベンチマーク JRuby

# Right single rotation # # b d # / \ / \ # a D -> B E # / \ / \ # c E a c # def rotate_left root = @right @right = root.left root.left = self root.swap_color(root.left) root end

# Left single rotation # # d b # / \ / \ # B e -> A D # / \ / \ # A c c e # def rotate_right root = @left @left = root.right root.right = self root.swap_color(root.right) root end

手続き的な木の回転...

Page 21: JavaOne Tokyo JVM言語BOF ベンチマーク JRuby

# Right single rotation # # b d # / \ / \ # a D -> B E # / \ / \ # c E a c # def rotate_left root = @right @right = root.left root.left = self root.swap_color(root.left) root end

# Left single rotation # # d b # / \ / \ # B e -> A D # / \ / \ # A c c e # def rotate_right root = @left @left = root.right root.right = self root.swap_color(root.right) root end

逆方向もベタ書き...

Page 22: JavaOne Tokyo JVM言語BOF ベンチマーク JRuby

class RBTreeMap class << self alias newInstance new end

def initialize @root = RBTree::EMPTY end

def get(key) @root.retrieve(key) end

def put(key, value) @root = @root.insert(key, value) @root.make_as_root value end

def height @root.height endend

赤黒木(RBTree)を使った連想配列(RBTreeMap)

https://github.com/nahi/javaone2012-benchmark

※CRuby完全互換

Page 23: JavaOne Tokyo JVM言語BOF ベンチマーク JRuby

CRubyとの比較

Page 24: JavaOne Tokyo JVM言語BOF ベンチマーク JRuby

JavaのHashMapとの比較