mrubyのFiberを
試してみた

Rubyist九州、近畿⼤大学
⼭山崎重⼀一郎郎
Fiberと関数
¡ Fiber:  オブジェクトを継続利利⽤用する
¡ 関数:呼ばれるたびに動作環境を⽣生成
組込み処理理
¡ 永続的なプロセスが動いている
定期的なメモリーの開放が必要

¡ センサーからの時系列列データの収集
正確な時間間隔で動いてほしい
GCで不不意に⽌止まるのは困る
実験してみた
¡ Rubyとmrubyを使⽤用(MacOSX上で)
¡ RubyはGC.statでヒープ量量を計測可能
¡ mrubyは実⾏行行時間のみ計測可能
GC.stat
Rubyの動作環境
GC.stat
{
    :count                    =>  18,                     #GCの回数
    :heap_̲used            =>  77,    
#
    :heap_̲length        =>  77,
    :heap_̲increment  =>  0,
    :heap_̲live_̲num    =>  23287,  #⽣生きているヒープの数
    :heap_̲free_̲num    =>  8115,
    :heap_̲final_̲num  =>  0,
}
移動平均
¡ センサーからのデータの系列列の平均
新しい⼊入⼒力力のたびに計算
バッファのサイズは⼀一定
移動平均関数版

(バッファはクロージャでメモ化)
SIZE=256	 	 	 	 	 	 	 	 	 	 	 	 	 



#バッファサイズ


aveb=lambda{|b|i=0	 	 	 



#クロージャ作成用関数


	 	 lambda{b[i]=rand(1024)	 	 #センサー入力のつもり

	 	 	 	 i=(i+1)%SIZE

	 	 	 	 b.reduce(:+).to_f/SIZE}}	 #移動平均の計算

buf=Array.new(SIZE,0)

ave=aveb[buf]	 	 








	 	 #移動平均関数の生成
移動平均ファイバ版
SIZE=256

avefb=lambda{|b|i=0

	 	 Fiber.new{loop{b[i]=rand(1024)

	 	 	 	 i=(i+1)%SIZE

	 	 	 	 Fiber.yield	 b.reduce(:+).to_f/SIZE}}}

buf=Array.new(SIZE,0)

avef=avefb[buf]
1e+05

C-Rubyで
関数を100回実⾏行行したときの
ヒープサイズと実⾏行行時間の変化

4e+04

ヒープサイズ

6e+04

rubyfunc

8e+04

    

0

20

40

60

80

100

rt

実⾏行行時間

0.0150 0.0155 0.0160 0.0165 0.0170

Time

0

20

40

60
Time

80

100
C-Rubyで
Fiberを100回実⾏行行したときの
ヒープサイズと実⾏行行時間の変化

29000
27000

f

ヒープサイズ

31000

              

20

40

60

80

100

60

80

100

Time

0.018 0.019 0.020 0.021 0.022 0.023

実⾏行行時間

t

0

0

20

40
Time
mrubyは
GCがちょっと違う
¡ インクリメンタルに⾏行行われる
¡ GC.statはない
¡ コンパイルされる
mruby
実⾏行行時間移動平均関数版

0.125
0.123

t1

0.127

0.129

      

0

20

40

60
Time

80

100
mruby
実⾏行行時間移動平均ファイバー版

0.130
0.128
0.126

t

0.132

0.134

      

0

20

40

60
Time

80

100
----ave.rb--

SIZE=256

aveb=lambda{|b|i=0

	 	 lambda{b[i]=rand(1024)

	 	 	 	 i=(i+1)%SIZE

	 	 	 	 b.reduce(:+).to_f/SIZE}}

buf=Array.new(SIZE,0)

ave=aveb[buf]

test1=lambda{m=[]

	 	 100.times{t0=Time.now

	 	 	 	 (1..1000).map{ave[]}

	 	 m.push	 (Time.now-t0)}

m}

puts	 test1[]


mruby
移動平均関数版
----avefb.rb--

SIZE=256

avefb=lambda{|b|i=0

	 	 Fiber.new{loop{b[i]=rand(1024)

	 	 	 	 i=(i+1)%SIZE

	 	 	 	 Fiber.yield	 b.reduce(:+).to_f/
SIZE}}}

buf=Array.new(SIZE,0)

avef=avefb[buf]

test2=lambda{m=[]

	 	 100.times{t0=Time.now

	 	 	 	 (1..1000).map{avef.resume}

	 	 m.push	 (Time.now-t0)}

m}

puts	 test2[]


mruby
移動平均Fiber版

mrubyのfiberを試してみた