JavaOne Tokyo JVM言語BOF ベンチマーク JRuby
-
Upload
hiroshi-nakamura -
Category
Documents
-
view
1.538 -
download
1
description
Transcript of JavaOne Tokyo JVM言語BOF ベンチマーク JRuby
赤黒木ベンチマークのポイント
JVM言語 × ロジックヘビーなプログラム
速度性能?コードの読み易さ?
赤黒木は最近雑誌で紹介され、馴染みがあった Groovy、Scala、JRubyで比較
さらにJava、Groovy++、CRubyも
赤黒木とは
データ構造の一種: 平衡二分木(バランス木)他の平衡二分木に比べ「ほどほど」のバランスデータ追加・削除後のバランス調整が楽
B
A D
C E
F
D
B E
C FA
AVL木 赤黒木
レギュレーション: 連想配列RBTreeMap
詳細: http://bit.ly/RedBlackTreeBenchmark RBTreeMapは以下のAPIを持つ。
put(String key, String value) => Objectkeyに対してvalueを結びつける。keyにはStringの
同値性、順序性を期待できるものとする。get(String key) => String
keyに対して割り当てられている値を返す。
型は各言語におけるString相当の型を扱えればよい。
マルチスレッドからアクセスされた場合の挙動は未定義。
レギュレーション: ベンチマーク取得方法
RBTreeMapをインスタンス化する。
用意したファイルを開き、全てを読み終わるまで以下を繰り返す。
ファイルから1行読み込み、key、value文字列を取り出す。
RBTreeMap#put(key, value)を呼ぶ。
再度同じファイルを開き、全てを読み終わるまで以下を繰り返す。
ファイルから1行読み込み、key、value文字列を取り出す。
RBTreeMap#get(key)がvalueと一致することを確認する。
上記全体の経過時間を5回計測し、中間3値の平均を取る。
入力データ
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が全て同じ値。
ベンチマーク環境
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)
JRuby版ソースコード解説
赤黒木ベンチマーク
https://github.com/nahi/javaone2012-benchmark
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行
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のメソッド
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の定義
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
木の末端(葉)にある「空」の定義
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と異なるのに注意
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の簡易定義
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
メソッド名末尾に?が使える
# 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
挿入は再帰で実装
# 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
参照はループで実装
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
末端への挿入により木が大きくなる
# 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
リズムよく、山の形の定義が連なる
# 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
手続き的な木の回転...
# 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
逆方向もベタ書き...
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完全互換
CRubyとの比較
JavaのHashMapとの比較