SlideShare una empresa de Scribd logo
1 de 71
Descargar para leer sin conexión
で高速なプログラムを
書く
川崎 会議 基調講演
遠藤侑介
1
自己紹介:遠藤侑介
• Ruby コミッタ(2008年~)
– Rubyのテストを増強した
– コードカバレッジ測定機能を
実装した
– キーワード引数を実装した
– Ruby 2.0 リリースマネージャ
だった
– 最近は何もしてない
2
’06下 ’07上 ’07下 ’08上
60
70
80
90
100
coverage(%)
70%
85%
C0カバレッジ遷移
と私
• 立ち上げの時に @chezou さんに相談を受けた
• 初期に数回だけ参加した
• Kawasaki.rb #005 (2013-10-23)で発表した
– 以上(すみません)
• ちなみに Kawasaki.rb #005 で発表したものは
3
eval$s=%q(eval(%w(B=92.chr;N=10.chr;n=0;e=->(s){Q[Q[s,B],?"].gsub(N,B+?n)};E=->(s){'("'+e[s]+'")'};d=->(s,t=?")
{s.gsub(t){t+t}};Q=->(s,t=?$){s.gsub(t){B+$&}};puts(eval(%q(%(objectXQRXextendsXApp{H("#{e[%((displayX"#{e[%(Hf
X%sX"#{Q[e["TranscriptXshow:X'#{d[%(putsX [regsub X-allX{. }X"#{Q[e[%[intXK(){sJXs=#{E[%(withXAda.Text_Io;pro
cedureXqrXisXbeginXAda.Text_Io.P ut_Li ne(" #{d[ %(BEGINXH("#{d[%(BEGIN{s=#{E[%(forXbXinXSystem.Text
.ASCIIEncoding().GetBytes(#{Q[ E[" # include<stdio.h>`nintXK(){puts#{E["#includ
e<iostream>`nintXK(){s td::c o ut<<#{E[%(classXProgram{publicXstaticXvoidX
Main(){System.Console .Wr ite(#{E[%((defnXf[lXr](if(>(count
Xr)45)(lazy-seq(cons ( str"XXXX^""r"^"&")(fXl"")))(let[c(
firstXl)](ifXc(f(ne xtXl)(if(=XcX^")(strXrXcXc)
(strXrXc)))[(str"X XXX^""r"^".")]))))(doall(map
X#(Hln(str"XXXXXX XX"%1))(lazy-cat["IDENT
IFICATIONXDIVISI ON.""PROGRAM-ID.XQR.""PR
OCEDUREXDIVISI ON."]#{(" console.log"+E[%((wr
ite-line"#{Q [%(X:XAX."XXXXXXXXX"X;X:X BXAX."XWRITE(*,*)'"XA
X;X:XCXBXTY PEX."X'"XCRX;X:XDXS"XprogramXQR"XC XS^"XHX^"(&"XCXS^"X#
{e[%(pack ageXK;import("fmt";"sJs");funcXK(){fmt.Pr int("H^x27"+sJs.Re
place("# {e[e[%(importXData.Char`nK=putStrLn$"procedure XK();write(^"DO,1
<-#"++s how(lengthXs)++fXsX1X0;f(x:t)iXc=letXv=foldl(^aXx- >a*2+(modXxX2))0
$takeX 8$iterate(flipXdivX2)$Data.Char.ordXxXin(ifXmodXiX4<1 then"PLEASE"els
e"")+ +"DO,1SUB#"++showXi++"<-#"++show(mod(c-v)256)++"^^n"++fX t(i+1)v;f[]_X_
="PL EASEREADOUT,1^^nPLEA SEGIVEUP^");end";s=#{E[%(.classXpublic XQR`n.superXja
va/l ang/Object`n.methodX publicXstaticXK([Ljava/lang/SJ;)V`n.lim itXstackX2`ng
ets taticXjava/lang/Syst e m/outXLjava/io/PrintStream;`nldcX"#{e[% (classXQR{pu
bli cXstaticXvoidXK(SJ[] v){ SJXc[]=newXSJ[8000],y="",z=y,s="#{z=t= (0..r=q=126)
.ma p{ |n|[n,[]]};a=[];%(@s =inte rnalXconstant[#{i=(s=%(PRX"#{Q["H"+E[% (all:`n`t@H
fX% sX"#{e[%(.assemblyXt {}.meth odXstaticXvoidXMain(){.entrypointXldst r"#{e["varX
u=re quire('u til');u.H('#import<stdio. h>^n');u.H(
#{E[% (in tXK(){puts #{E["H_ sJ"+E["Hf"+E[ %(say"# {e["programXQR(output);begi nX#{([*%($_
="#{s= %(<?phpXecho"#{Q [e["i ntXK(){write#{E ["qr: -write('#{Q[e[%(forXlXin#{E[ e[d[%(eval$
s=%q(#$s) )]]]}.split("^^n") :H( 'cat("sayX^^"'+l+ '^^ "^^n")'))],?']}'),nl,halt."]} ;returnX0;}
"]]}"?>);(s+N*( -s.size%6)).byt e s.map{|n|"%07b"%n}. j oin.gsub(/.{6}/){|n|n=n.to_i(2 );((n/26*6+
n+19)%83+46).ch r}}";s|.|$n=ord$ &;substrXunpack(B8,ch r$n-($n<58?-6:$n<91?65:71)),2|e g;s/.{7}/0$
&/g;HXpackXB.le ngth,$_).scan(% r (([X.0-9A-Za-z]+)|( . ))).reverse.map{|a,b|(b) ? "s//chrX#{b
.ord}/e":"s//#{ a}/"},"eval"] *"X xX").gsub(/.{1,25 5}/ ){|s|"write( ' # {s}');"}}
end."]}"`nend`n) ]]]};returnX 0;}). trXB,?@]}.repla ce(/@ /g,SJ.fr o m CharCode
(92)))"]}"callXv oidX[mscor lib]Sys tem.Console:: Write(s J)ret})]}")],/ [ X ^`t;"()
{}`[`]]/]}`nBYE)) .size+1}X xXi8]c"#{s.g s u b(/[^`
n"]/){B+"%02`x58" %$&.ord}}^00"declareX i32@put s(i8*)defineXi32@K(){star t:%0=cal l X i32@pu
ts(i8*Xgetelementp trXinbounds([#{i}XxXi 8]*@s ,i32X0,i32X0))retXi32X0}).bytes{|n | r ,z=z[
n]||(a<<r;q<5624&&z [n]=[q+=1,[]];t[n])}; a<< r;t=[*43..123]-[64,*92..96];a.map{|n | t[n/7
5].chr+t[n%75].chr}* ""}";intXi=0,n=0,q=0, t ;for(;++n<126;)c[n]=""+(char)n;for(; i <s.le
ngth();){t=s.charAt(i );q=q*75+t-t/64-t/92 *5-43;if(i++%2>0){y=q<n?c[q]:y;c[n+ + ]=z+
y.charAt(0);System.out .H(z=c[q]);q=0;}}}}) ]}"`ninvokevirtualXjava/io/PrintStr e am/H
ln(Ljava/lang/SJ;)V`nre turn`n.endXmethod)+N]})].trXB,?@]}^x27^n","@","^^",- 1))})]} "XDU
PXFORXS"X&A,&"XCXNE`x58TX S^"X&A)^",&"XCX0XDOXBX."X&char("XCOUNTX.X."X),&' "XCRXLOOP XS^"
X&^"^""XCXS"XendXprogramXQ R"XCXAX."XSTOP"XCRXAX."XEND"XCRXBYEX;XDX), /([^"])/]}"))]).gsu b(/.
+/){%((cons"DISPLAY"(f"#{e[$ &]}""")))}}["STOPXRUN."])))).trXB,?~ ]}.Replace("~","^^")); }})
]};}"]};returnX0;}"]]}):HXjoin( ['+'forXiXinXrange(0,b)],"") +".>").trXB,?!]};gsub(/! /,"
^^",s);HXs})]}")END)]}");endXqr;) ]};intXi,j;H( "moduleXQR;initialXbeginX");for(
i=0;i<s.length;i++){H("$write(^"XXX") ;for(j=6;j>=0;j--)H((s[i]>>j)%2>0?"
^^t":"X");H("^^n^^t^^nXX^`");");}H("$disp lay(^"^^n^^n^");endXendmodule");returnX0
;}].reverse],/[`[`]$]/]}"X^x60.&]k),?']}';cr"]]} ")]}")).gsubXB*8,?|]}".replaceAll("^^|","#{B*32
}"))})).gsub(/[HJK^`X]/){[:print,0,:tring,:main,B*2,0,B,?¥s][$&.ord%9]})))*"")#_buffer_for_future_bug_fixes_#_b
################### Quine Relay -- Copyright (c) 2013 Yusuke Endoh (@mametter), @hirekoke ##################)
• とある Ruby プログラム
• 実行すると Scala プログラムが出力される
• 実行すると Scheme プログラムが出力される
• …
• 実行すると REXX プログラムが出力される
• 実行すると元の Ruby プログラムが出力される
• ... というプログラム(50 段階の Multi-quine)
• (多分)世界初、50言語を使用するプロジェクト
• https://github.com/mame/quine-relay/tree/50
の発表の影響
• 不足言語の指摘をもとに、
50から100言語に増強しました
• Docker に対応しました
• @MakeNowJust さん
PR ありがとう
• GitHubのスター数が
2800 から 5100 に
増えました
• GitHub 一千万リポジトリ中
上位 1000 件(0.01%)に入る
6
『超絶技巧プログラミングの世界』
• こんなプログラムや
実装方法の解説が
いっぱい載ってます
– 技術評論社より発売中
7
閑話休題
• 今日の主題:Rubyで高速なプログラムを書く方法
8
アジェンダ
• 背景:Ruby3x3
• 事例:Optcarrot
• 最適化の心得
• プロファイラの使い方
• 最適化の具体例
• Ruby 処理系ベンチマーク
• 与太話
9
• Ruby開発チームの最近のスローガン
– “Ruby3 will be 3 times faster than Ruby2”
• 条件[Matz の RubyKaigi 2015 の発表より]
– 2020年ごろ
– 比較対象は Ruby 2.0
– ベンチマークは開発チームが選ぶ
• 小さいが人工的でないもの
– 省メモリよりスピード重視
10
チート?
開発者の悩み
• あらゆるプログラムを 3 倍速くするのは困難
– 今の Ruby は(スクリプト言語にしては)すでに相当高速
– 高速化すべきプログラムが高速になるようにしたい
• 『手軽』に試せるベンチマークプログラムがない
– Ruby コア開発者 = C 言語マスター ≠ Ruby ヘビーユーザ
– Rails のセットアップとか知らない
11
手軽なベンチマーク
• あなたのプログラムを『手軽』なベンチマークにして
公開しよう!
– あなたのプログラムが速くなる(かもしれない)
– Ruby 開発に貢献した気になれる(かもしれない)
• 『手軽』とは?
– 『手軽』で面白くて(一応)実用アプリである
ベンチマークプログラム事例として Optcarrot を作りました
12
アジェンダ
• 背景:Ruby3x3
• 事例:Optcarrot
• 最適化の心得
• プロファイラの使い方
• 最適化の具体例
• Ruby 処理系ベンチマーク
• 与太話
13
とは
• Rubyで書かれたNES(ファミコン)エミュレータ
Demo
14
開発動機
• Ruby3x3を煽るベンチマーク候補
– Ruby 2.0 で 20 fps で動く  Ruby 3.0 で 60 fps?
– CPU律速で現実的なベンチマーク
– 最適化ニンジン(Optimization Carrot)
• もう1つの動機:
Rubyで無理そうなことをやってみたかった
– NESの解像度:256 x 240 ピクセル x 60 fps
– ループ以外のタスクを 0.8 秒で?
(256*240*60).times do |i|
ary[0] = 0
end
0.2 秒
15
開発経緯
• 10年前:実装を試みるも断念
– 当時はRubyもCPUも遅すぎ、NES解析情報もいまいち
• 2015/11/08:大江戸 Ruby 会議 04
– Ruby で NES ROM を作るフレームワーク burn を見る
– http://wiki.nesdev.com/ を発見
• 2015/12/11-13:RubyKaigi 2015
– Ruby3x3 を聞き、一通り実装して 3 fps 程度になる
• 2015/12/29-31:冬休み前半に 20 fps 達成
• 2016/01/01-03:冬休み後半に 60 fps 達成
• 2016/04/01:公開
16
の関連研究
• Ruby でファミコンプログラミング
(takkaw, 2007)
– NES ROM でプレゼン
• Nario:MRI の段階的 GC のデモ
(authornari, 2008)
– マリオ風ゲームのもたつき現象で
リアルアイム性をデモした
• Burn (remore, 2014)
– Ruby で NES ROM を作れる
フレームワーク
17
のアーキテクチャ
CPU GPU
Program ROM Bitmap ROM
Cartridge
NES
RAM
(2 kB)
VRAM
(2 kB)
control
read
read/write
read
render
read/write
※NES 業界ではGPUではなく PPU (Picture Processing Unit) と言うようです
interrupt
18
APU
エミュレーションのボトルネック
GPU
80%
CPU
10%
その他
10%
実行時間比率
19
の仕事
• 背景描画(最大のボトルネック、次ページ)
• スクロール
– VRAMは2画面分あり、1画面分を描画する
• スプライト
– 背景にキャラチップを重ねて書ける
– 衝突判定:0番スプライトを描画するとき CPU 割り込みする
• GPUはNES大勝利の立役者
– 同時期のアーケードと遜色ないグラフィック
– 同時期の汎用機(数十万円)より良い(NES:1.5万円)
20
背景描画
• ピクセルごとに以下を実行 (1秒あたり256 x 240 x 60 = 3.7M回)
1. そこにあるビットマップ番号をタイル配置データから同定
2. パレット配置データを読んでパレットを同定
3. ビットマップ番号に対応するビットマップデータを読み込む
4. 組み合わせてビデオ信号にして送る
タイル配置データ
パレット配置データ
VRAM
GPU2
1
3
4
描画対象
正確には8ピクセル(1バイト)単位で処理する
21
画像データ
Cartridge
の仕事はとても大変
http://wiki.nesdev.com/w/index.php/File:Ntsc_timing.png
22
の仕事
• 「プログラムROMから命令を読み出して実行する」を
繰り返す
• CPU:MOS 6502
– 1.7 MHz
– レジスタ 8 ビット、アドレス空間 16 ビット
– 可変長命令(1 - 3 バイトくらい)
– 可変クロック(1 - 9 クロックくらい)
– パイプラインなし
– 大体秒間 30 万命令くらい処理する
• メインメモリ:2 kB
– ツイート約 5 つ分(UTF-8 日本語)
23
の仕事
• 以下の波形を合成して出力する
– 矩形波 x 2
– 三角波
– ノイズ
– PCM
– 簡単に言えば 3 和音+ドラム
• 実装は面倒だが、ボトルネックにはならない
– 44100 Hz なら、1 秒間に 44100 x O(1) の処理でよい
– GPU は 256x240x60 = 3686400 x O(1) の処理が必要
– ノイズ生成のみ若干重い
24
と の通信
• CPUから見てGPUとAPUはメモリに見える
– アドレス0x2000番地に書き込むとGPUへの情報送信
– アドレス0x2000番地から読み込むとGPUからの情報取得
25
アドレス 内容
0x0000..0x07ff 普通のメモリ
0x2000..0x3fff GPU
0x4000..0x5fff APUとパッド
0x6000..0x7fff 拡張メモリ
0x8000..0xffff プログラムROM
char *gpu = (char*)0x2000;
*gpu = 0x01;
マッパー
• ファミコンカートリッジは単なるソフトウェアではない
– 各ゲーム専用の回路が組み込まれている
– 発売されたゲームの数だけ回路がある
• ROM ファイルには回路の番号だけが書かれている
– マッパーと呼ばれる
• 実用的なエミュレータは、
発売されたゲームの数だけある回路を
すべて実装しないといけない
– Optcarrot は基本的なマッパーしか対応していない
26
基本的なエミュレーション方法
• GPU・CPU・APU の機能をソフトウェアで実装する
– メモリを整数の配列で表す
– 「メモリを読み出し、何か計算し、メモリに書き戻す」
を繰り返す
27
アジェンダ
• 背景:Ruby3x3
• 事例:Optcarrot(NESエミュレータ)
• 最適化の心得
• プロファイラの使い方
• 最適化の具体例
• Ruby 処理系ベンチマーク
• 与太話
28
最適化の心得
1. 目標値を設定せよ
2. ボトルネックをいじれ
3. アルゴリズム最適化を考えよ
4. 効果を検証せよ
29
目標値を設定せよ
• 最適化=コードを汚すこと
– 目標値を設定しないと際限なくコードを汚くしてしまう
• 目標値がないと「小さなことからコツコツと」をやりがち
– 大きなことからやれ
– 「わずかでも速くしたい」という煩悩は諸悪の根源
– 本当にとにかく速くしたいなら C 言語へどうぞ
• 「XXまで速くすれば○○できる、しないとできない」と
いう目標がよい
– 開発効率・メンテナンス性・マーケティングなどから決める
– 達成できるかどうかで価値がまったく変わるのが望ましい
• NESの場合 60 fps
30
ボトルネックをいじれ
• 「2 倍高速化」「10%高速化」どっちが良いか?
– 答え:不明(それがボトルネックかどうかによる)
• 計算時間10%の処理を2倍高速化全体の5%削減
• 計算時間80%の処理を10%高速化全体の8%削減
– ボトルネックの特定にはプロファイラを使う(後述)
31
アルゴリズム最適化を考えよ
• Optcarrot の場合
– ナイーブに書いて 3 fps
– アルゴリズム・データ構造の改善で 20 fps (約 7 倍)
– メソッド展開とか汚いことやって 80 fps (約 4 倍)
• アルゴリズム改善の方が寄与度が高い
– アルゴリズムに工夫の余地がなさそうなエミュレータですら
– メソッド展開などはわかりやすくて印象に残りやすいが、
通常はメンテナンス性を犠牲にするほどの効果はない
32
効果を検証せよ
• ×「実行してみたら速かった」
– 測定のたびにブレがある
– 都合のいい結果を記憶に残して「速くなった」と信じてしまう
• 確証バイアス:仮説や信念を検証する際にそれを支持する情報ばか
りを集め、反証する情報を無視または集めようとしない傾向のこと
• 今回:最適化前と後で 30 回ずつ実行時間を計測、
Welch の t 検定で 5% 有意差があることを確認した
• 有意差が認められなかったら変更を捨てる  重要
– 頑張って実装した最適化が効果なかったとは認めたくない
ものだが、Mottainai の精神は悪
33
アジェンダ
• 背景:Ruby3x3
• 事例:Optcarrot
• 最適化の心得
• プロファイラの使い方
• 最適化の具体例
• Ruby 処理系ベンチマーク
• 与太話
34
• a sampling call-stack profiler for ruby 2.1+
– https://github.com/tmm1/stackprof
• 特徴
– オーバーヘッドがほとんどない
– 測定結果は正確ではない
• インタプリタを数ミリ秒おきに監視し、各タイミングでどのメソッドが
実行されているかカウントする(サンプリングプロファイラ)
– 使うためにコードを書き換える必要がある
• 対抗:ruby-prof
– 使いやすい:ruby foo.rb を ruby-prof foo.rb にするだけ
– 測定結果が正確:メソッドごとの呼び出し回数
– オーバーヘッドがヤバい
35
の使い方
1. 測りたい部分を以下で囲む
– Optcarrot は初期化後のメインループを囲んでいる
2. 実行する  stackprof.dump ファイルができる
3. stackprof stackprof.dump で結果を見る
– render_pixelが実行時間の20%を占めていることがわかる
36
TOTAL (pct) SAMPLES (pct) FRAME
274 (19.3%) 274 (19.3%) Optcarrot::PPU#render_pixel
160 (11.3%) 160 (11.3%) Optcarrot::PPU#wait_one_clock
106 (7.5%) 105 (7.4%) Optcarrot::CPU#fetch
StackProf.run(mode: :cpu, out: "stackprof.dump") {
# 測定したいコード
}
メソッド単位のプロファイル結果
37
$ stackprof --method "Optcarrot::PPU#render_pixel"¥
stackprof-cpu.dump
Optcarrot::PPU#render_pixel (/home/mame/work/optcarrot/lib/optcarrot/pp
samples: 309 self (17.8%) / 309 total (17.8%)
callers:
309 ( 100.0%) Optcarrot::PPU#main_loop
code:
| 803 | def render_pixel
| 804 | if @any_show
186 (10.7%) / 186 (10.7%) | 805 | pixel = @bg_enable
17 (1.0%) / 17 (1.0%) | 806 | if @sp_active && (
| 807 | if pixel % 4 ==
| 808 | pixel = sprite
| 809 | else
| 810 | @sp_zero_hit =
| 811 | pixel = sprite
| 812 | end
| 813 | end
| 814 | else
5 (0.3%) / 5 (0.3%) | 815 | pixel = @scroll_ad
プロファイリングの命は可視化
38
$ stackprof --callgrind stackprof.dump ¥
> stackprof.callgrind
$ kcachegrind stackprof.callgrind
オブジェクト生成の計測
39
$ stackprof obj.dump
==================================
Mode: object(1)
Samples: 86283 (0.00% miss rate)
GC: 0 (0.00%)
==================================
TOTAL (pct) SAMPLES (pct) FRAME
86278 (100.0%) 86278 (100.0%) Optcarrot::PPU#main_loop
86282 (100.0%) 4 (0.0%) Optcarrot::PPU#run
1 (0.0%) 1 (0.0%) Optcarrot::CPU#run
5 (0.0%) 0 (0.0%) Optcarrot::NES#step
5 (0.0%) 0 (0.0%) Optcarrot::NES#run
5 (0.0%) 0 (0.0%) <main>
5 (0.0%) 0 (0.0%) <main>
StackProf.run(mode: :object, out: “obj.dump") {
# 測定したいコード
}
参考:
• Rubyの実装レベルでボトルネックを見るときに使う
• 評価器が時間の半分、インスタンス変数読み込みが
16% 、メソッド探索が 6% 占めているとわかる
– perf については“RubyKaigi 2015 kosaki keynote”で検索
40
51.76% ruby ruby [.] vm_exec_core
16.18% ruby ruby [.] vm_getivar.isra.99
5.89% ruby ruby [.] vm_search_method.isra.79
$ perf record ruby ...
$ perf report
アジェンダ
• 背景:Ruby3x3
• 事例:Optcarrot
• 最適化の心得
• プロファイラの使い方
• 最適化の具体例
• Ruby 処理系ベンチマーク
• 与太話
41
アルゴリズム改善:
• ナイーブな実装:CPUとGPUの
エミュレーションを
クロック単位で切り替える
– 簡単で正確だが切り替えコストがかかって遅い(3fps)
CPU step
step
step
step
step
step
step
step
step
step
step
step
step
step
step
step
clock
GPU
42
loop do
@cpu.step
@gpu.step
end
アルゴリズム改善:
• キャッチアップ法:
CPUがGPUを制御したら
切り替える
– 正確で高速(10fps)(実装は大変だけど頑張る)
CPU run
catchup
run
catchup
run
clock
GPU CPU attempts to
control GPU
43
loop do
clks = @cpu.run
@gpu.catchup(clks)
end
アルゴリズム改善: 実装
• ナイーブな実装:ピクセル単位でエミュレーションする
– ハードウェアと同じことをする
画像データ
タイル配置データ
パレット配置データ
VRAM
GPU2
1
3
4
この計算をピクセルごとにやるので遅い
(一回の計算は大したことないが、一秒間に256 x 240 x 60 回やる)
44
Cartridge
アルゴリズム改善: 実装
• スクリーンを事前描画して、変更部分のみ更新する
タイル配置データ
パレット配置データ
VRAM
GPU
screen buffer
VRAMが書き換わった 変更部分のみ更新
フレームごとに
ビデオ出力
※この説明はイメージです 45
画像データ
Cartridge
• CPUはGPUやAPUをメモリ越しに制御する
• メモリアクセスのナイーブな実装:
– 毎回条件判定するのは遅い
– メモリマップはカートリッジによって変わるので
ハードコーディングはいけてない
def memory_read(addr)
case addr
when 0x0000..0x07ff then @main_memory[addr]
when 0x2000..0x3fff then @gpu.read(addr)
...
end
end
46
• Method#[] と Array#[] が同名なのを利用したコード
– 普通のメモリアクセスは配列参照 2 回でいける
– GPU・APU制御の場合は Method#[] で対応メソッドが
呼び出される
@mem = []
@mem[0x0000] = @main_memory
...
@mem[0x2000] = @gpu.method(:read)
...
def memory_read(addr)
@mem[addr][addr]
end
47
その他の最適化
• アルゴリズム最適化でも漸近的計算量だけを見ない
– 例:Ruby でリングバッファを実装するより、長さ次第では
Array#rotate!を使った方が速いことも
• いろいろ事前計算する
• こんな感じで 20 fps を達成した
– Intel® Core™ i7-4500U @ 2.40 GHz / Ubuntu 16.04
0x23C0 |
(addr & 0x0C00) |
(addr >> 4 & 0x0038) |
(addr >> 2 & 0x0007)
ARY[addr]
48
ここから闇
• ここまではプログラムの綺麗さは比較的維持していた
• ここからは、プログラムを汚くして高速化する
– 普通のRubyプログラマがマネするべき手法ではありません
– Rubyインタプリタの高速化の余地を図る研究です
49
™ 手動メソッド展開
• メソッド呼び出しは遅いので展開する
(当然ボトルネックのみ)
while catchup?
inc_addr
end
while catchup?
@addr += 1
end
28 fps  40 fps
50
™ インスタンス変数のローカル変数化
• インスタンス変数アクセスが遅い
– ローカル変数に置き換える
while catchup?
@addr += 1
end
begin
addr = @addr
while catchup?
addr += 1
end
ensure
@addr = addr
end
40 fps  47 fps
51
• 典型的な実行パスを展開する
™ while catchup?
if can_be_fast?
# fast-path
do_A
do_B
do_C
@clock += 3
else
case @clock
when 1 then do_A
when 2 then do_B
when 3 then do_C
...
end
@clock += 1
end
end
while catchup?
case @clock
when 1 then do_A
when 2 then do_B
when 3 then do_C
...
end
@clock += 1
end
47 fps  63 fps 52
各 ™ の効果
29.4
40.3
46.6
62.7
68.8
83.2
0.0 20.0 40.0 60.0 80.0
base
method inlining
ivar localization
fastpath
misc
CPU misc
ProTip™ 1
ProTip™ 2
ProTip™ 3
53
実装上の工夫
• 手動と言っても本当に手動にはしない
– 正規表現を使って自動的に変換する
• コードのインデントを頼りにパースする
– コードのインデントがちゃんとしている前提
– コードチェッカ Rubocop を使って、
コードのインデントが変になっていないことを検証する
src = File.read(__FILE__)
src.gsub!(/.../) { ... } # method inlining
src.gsub!(/.../) { ... } # ivar localization
eval(src)
54
アジェンダ
• 背景:Ruby3x3
• 事例:Optcarrot
• 最適化の心得
• プロファイラの使い方
• 最適化の具体例
• Ruby3x3 のためのベンチマーク
• 与太話
55
の前に、テスト用 の入手方法
• 有志がスクラッチから作ったROMがある
– http://www.romhacking.net/
– ベンチマーク用にはこちら(Lan master を使用)
• もう1つの手段:実際のカートリッジから抽出する
– このための回路を通称で「吸出し器」と呼ぶ
56
自作した吸出し器
57
自作した吸出し器
※吸出しプログラムも Ruby で書かれている
(arduino_fermata gem を利用) 58
Arduino + Firmata
自作シールド
(「ホンコン」ベース)
カートリッジ
接触悪い
パスコンなし
ベンチマーク(アルゴリズム改善)
28.7
28.1
25.5
26.6
25.0
21.4
5.83
21.9
39.2
25.0
4.10
7.48
27.0
0.0287
0.0 10.0 20.0 30.0 40.0
trunk
ruby23
ruby22
ruby21
ruby20
ruby193
ruby187
omrpreview
jruby9k
jruby17
rubinius
mruby
topaz
opal
59
MRI は改善されている
(1.81.92.02.3)
OMR は速くない?
(MRI 2.2 w/ JIT)
JRuby9k が最速
ruby 2.0 で >20 fps
(Ruby3x3 的に重要)
こんなのでも動く
ベンチマーク(+闇)
28.6
28.0
25.2
26.9
26.1
21.4
5.87
22.8
39.3
25.3
3.97
7.02
29.3
0.0285
84.0
82.9
78.2
79.6
68.1
64.0
1.46
69.0
2.12
6.13
2.43
0.754
0.0501
0.0 10.0 20.0 30.0 40.0 50.0 60.0 70.0 80.0 90.0
trunk
ruby23
ruby22
ruby21
ruby20
ruby193
ruby187
omrpreview
jruby9k
jruby17
rubinius
mruby
topaz
opal
default mode optimized mode
生成したソースコードは
JVM 64k バイトコード制限に
ひっかかるので JIT できない
とのこと
60
考察
• JRuby 9k が最速: “Deoptimization” が有望
– レアケースを無視して最適化 JIT コンパイルしておく
– レアケースが発生したら、そこだけ JIT コンパイルしなおす
 卜部さんが検討中?
https://github.com/shyouhei/ruby/tree/deoptimization_base
• OMR はあまり速くない?
– JIT は望み薄?
• perf によると 50% が評価器だが、これは基本的な組み込みメソッド
の処理を含んでいる
– OMR はできたばかり
• チューニングの余地はあるし、opt_case_dispatch (case 文)の
最適化がまだっぽい
61
不完全な 実装との戦い
• mruby:
– require なし、module_function なし、 fiber なし、
モジュールのインクルードがなんか微妙
• topaz:
– String#tr や #% を使ったら異常終了することがある
• opal:
– パスが動的な require 禁止、binread を自力実装
• 適当な shim を作った
– shim 不要なのは MRI と JRuby 9.1.0.0 だけ
62
ベンチマークプログラム
• コード生成含めて 5000 行以下
• 非GUIモードならライブラリ一切不要
– miniruby(MRI開発用の不完全なRuby実装)でも動く
– GUIモードでは ruby-ffi 経由でSDL2 を使う
• 基本的な Ruby 機能しか使っていない
– ruby 1.8 / mruby / topaz / opal でも shim などで動く
• Ruby開発者がRubyの高速化を検証する流れ
– miniruby ビルド→ miniruby 実行
63
よく使われるベンチ:
• 30000行超
• セットアップ手順
– PostgreSQL の設定
– Redmine インストールと初期設定と初期データ登録
– Apache のインストールと設定
– Passenger のインストールと設定
• Ruby開発者がRubyの高速化を検証する流れ
– Ruby 全ビルド→インストール→(Apache再起動?)→
ab 実行
64
『手軽』なベンチマーク
• Ruby開発者にとって『手軽』であることが重要
• インストールやセットアップが不要
– git clone だけとコマンド一発で
標準的な設定とデータセットが準備できると理想
• コマンドラインから ruby foo.rb で起動・終了する
– 「このコマンドの実行時間を短縮せよ」だとわかりやすい
• 数秒くらいで終わり、毎回の実行時間が安定しているとより良い
– rake や rack 経由で実行するのはめんどい
• プロファイラやデバッガが使いにくい
• Ruby 開発者の Ruby は /usr/bin/ruby にはない
• 依存関係が少ないこと、そんなに大きくないこと、など
– miniruby で動くと理想(拡張ライブラリなし)
65
は適切なベンチマーク?
• 「遅いRubyには向いてないアプリでは?」
– もう Ruby はそこまで遅くない
– 「科学技術計算向き」とされる Python よりも
(コア自体は)速くなってきている
• 「にしても、エミュレータはRubyの目指すところか?」
– 個人的にはこういうのも書ける言語になってほしい
– 他のものを高速化してほしい人は、自分なりの
ベンチマークプログラムを作って公開してください
66
アジェンダ
• 背景:Ruby3x3
• 事例:Optcarrot
• 最適化の心得
• プロファイラの使い方
• 最適化の具体例
• Ruby 処理系ベンチマーク
• 与太話
67
プログラミング言語は道具?
• 「言語は道具。用途に応じて使い分けるべき。」
– 本当?
• 「言語は道具」?
– 自然言語は思考・意思を伝達する道具というが
– 思考・意思は言語と独立している?本当に?
• 「用途に応じて使い分けるべき」?
– 言語の習得はコストが高い
– 適応力がある人 or ニワカな人 or コードを書かない人
68
つの言語にこだわる つの理由
• 言語が「脳のキャッシュ」に載る
– リファレンスを見ずにプログラムできる
– ストレスなくプログラミングするために重要
– 多数の言語をこの状態にするのは(自分は)難しい
• 言語の「土地勘」が身につく
– その言語「らしい」書き方がわかる
– 「らしい」書き方だと、効率的なプログラムになったり、
バージョンアップ時のハマりを減らせたりする
– 言語機能の熟練度が予想できる(akr プロダクトは安心)
• 言語の「守備範囲」がよくわかる
– その言語でできることは思ったより広い
69
注意
• 他言語を勉強しなくていいわけではない
– 見識は広げるべき
– ただ、「広く浅く」だけでは見えてこないものもある
• 何が何でも 1 つの言語で完結させる必要はない
– 工夫しまくってファミコンエミュレータが書けたが
– 工夫せずに実速が出せる C 言語の方が適切なのは確か
– ただ、ちょっとした工夫で言語を変えせずに済む場合も多い
• エコシステムの存在はでかい
– 科学技術計算やるなら Python に戦ってもしょうがない
– 再発明のコストが新言語習得のコストを明らかに上回る
70
まとめ
• Rubyで高速プログラムを書く方法を紹介しました
– 背景:Ruby3x3
– 事例:Optcarrot
– 最適化の心得
– プロファイラの使い方
– 最適化の具体例
– Ruby 処理系ベンチマーク
– 与太話
71

Más contenido relacionado

La actualidad más candente

20221226_TITECH_lecture_ishizaki_public.pdf
20221226_TITECH_lecture_ishizaki_public.pdf20221226_TITECH_lecture_ishizaki_public.pdf
20221226_TITECH_lecture_ishizaki_public.pdfKazuaki Ishizaki
 
O/Rマッパーによるトラブルを未然に防ぐ
O/Rマッパーによるトラブルを未然に防ぐO/Rマッパーによるトラブルを未然に防ぐ
O/Rマッパーによるトラブルを未然に防ぐkwatch
 
Javaコードが速く実⾏される秘密 - JITコンパイラ⼊⾨(JJUG CCC 2020 Fall講演資料)
Javaコードが速く実⾏される秘密 - JITコンパイラ⼊⾨(JJUG CCC 2020 Fall講演資料)Javaコードが速く実⾏される秘密 - JITコンパイラ⼊⾨(JJUG CCC 2020 Fall講演資料)
Javaコードが速く実⾏される秘密 - JITコンパイラ⼊⾨(JJUG CCC 2020 Fall講演資料)NTT DATA Technology & Innovation
 
例外設計における大罪
例外設計における大罪例外設計における大罪
例外設計における大罪Takuto Wada
 
DDDのモデリングとは何なのか、 そしてどうコードに落とすのか
DDDのモデリングとは何なのか、 そしてどうコードに落とすのかDDDのモデリングとは何なのか、 そしてどうコードに落とすのか
DDDのモデリングとは何なのか、 そしてどうコードに落とすのかKoichiro Matsuoka
 
磯野ー!関数型言語やろうぜー!
磯野ー!関数型言語やろうぜー!磯野ー!関数型言語やろうぜー!
磯野ー!関数型言語やろうぜー!Ra Zon
 
Lispとは何なのか - 同図像性がもたらす力とその利用法
Lispとは何なのか - 同図像性がもたらす力とその利用法Lispとは何なのか - 同図像性がもたらす力とその利用法
Lispとは何なのか - 同図像性がもたらす力とその利用法Naoya Yamashita
 
何となく勉強した気分になれるパーサ入門
何となく勉強した気分になれるパーサ入門何となく勉強した気分になれるパーサ入門
何となく勉強した気分になれるパーサ入門masayoshi takahashi
 
GraalVMのJavaネイティブビルド機能でどの程度起動が速くなるのか?~サーバレス基盤上での評価~ / How fast does GraalVM's...
GraalVMのJavaネイティブビルド機能でどの程度起動が速くなるのか?~サーバレス基盤上での評価~ / How fast does GraalVM's...GraalVMのJavaネイティブビルド機能でどの程度起動が速くなるのか?~サーバレス基盤上での評価~ / How fast does GraalVM's...
GraalVMのJavaネイティブビルド機能でどの程度起動が速くなるのか?~サーバレス基盤上での評価~ / How fast does GraalVM's...Shinji Takao
 
Linuxにて複数のコマンドを並列実行(同時実行数の制限付き)
Linuxにて複数のコマンドを並列実行(同時実行数の制限付き)Linuxにて複数のコマンドを並列実行(同時実行数の制限付き)
Linuxにて複数のコマンドを並列実行(同時実行数の制限付き)Hiro H.
 
実践イカパケット解析
実践イカパケット解析実践イカパケット解析
実践イカパケット解析Yuki Mizuno
 
世界一わかりやすいClean Architecture
世界一わかりやすいClean Architecture世界一わかりやすいClean Architecture
世界一わかりやすいClean ArchitectureAtsushi Nakamura
 
ドメインロジックに集中せよ 〜ドメイン駆動設計 powered by Spring
ドメインロジックに集中せよ 〜ドメイン駆動設計 powered by Springドメインロジックに集中せよ 〜ドメイン駆動設計 powered by Spring
ドメインロジックに集中せよ 〜ドメイン駆動設計 powered by Spring増田 亨
 
TRICK 2022 Results
TRICK 2022 ResultsTRICK 2022 Results
TRICK 2022 Resultsmametter
 
トランザクションの設計と進化
トランザクションの設計と進化トランザクションの設計と進化
トランザクションの設計と進化Kumazaki Hiroki
 
OSS についてあれこれ
OSS についてあれこれOSS についてあれこれ
OSS についてあれこれTakuto Wada
 
Pythonによる黒魔術入門
Pythonによる黒魔術入門Pythonによる黒魔術入門
Pythonによる黒魔術入門大樹 小倉
 
JAVA_HOME/binにあるコマンド、いくつ使っていますか?[JVM関連ツール編](JJUGナイトセミナー「Java解析ツール特集」 発表資料)
JAVA_HOME/binにあるコマンド、いくつ使っていますか?[JVM関連ツール編](JJUGナイトセミナー「Java解析ツール特集」 発表資料)JAVA_HOME/binにあるコマンド、いくつ使っていますか?[JVM関連ツール編](JJUGナイトセミナー「Java解析ツール特集」 発表資料)
JAVA_HOME/binにあるコマンド、いくつ使っていますか?[JVM関連ツール編](JJUGナイトセミナー「Java解析ツール特集」 発表資料)NTT DATA Technology & Innovation
 

La actualidad más candente (20)

OS入門
OS入門OS入門
OS入門
 
20221226_TITECH_lecture_ishizaki_public.pdf
20221226_TITECH_lecture_ishizaki_public.pdf20221226_TITECH_lecture_ishizaki_public.pdf
20221226_TITECH_lecture_ishizaki_public.pdf
 
O/Rマッパーによるトラブルを未然に防ぐ
O/Rマッパーによるトラブルを未然に防ぐO/Rマッパーによるトラブルを未然に防ぐ
O/Rマッパーによるトラブルを未然に防ぐ
 
Javaコードが速く実⾏される秘密 - JITコンパイラ⼊⾨(JJUG CCC 2020 Fall講演資料)
Javaコードが速く実⾏される秘密 - JITコンパイラ⼊⾨(JJUG CCC 2020 Fall講演資料)Javaコードが速く実⾏される秘密 - JITコンパイラ⼊⾨(JJUG CCC 2020 Fall講演資料)
Javaコードが速く実⾏される秘密 - JITコンパイラ⼊⾨(JJUG CCC 2020 Fall講演資料)
 
OAuth 2.0のResource Serverの作り方
OAuth 2.0のResource Serverの作り方OAuth 2.0のResource Serverの作り方
OAuth 2.0のResource Serverの作り方
 
例外設計における大罪
例外設計における大罪例外設計における大罪
例外設計における大罪
 
DDDのモデリングとは何なのか、 そしてどうコードに落とすのか
DDDのモデリングとは何なのか、 そしてどうコードに落とすのかDDDのモデリングとは何なのか、 そしてどうコードに落とすのか
DDDのモデリングとは何なのか、 そしてどうコードに落とすのか
 
磯野ー!関数型言語やろうぜー!
磯野ー!関数型言語やろうぜー!磯野ー!関数型言語やろうぜー!
磯野ー!関数型言語やろうぜー!
 
Lispとは何なのか - 同図像性がもたらす力とその利用法
Lispとは何なのか - 同図像性がもたらす力とその利用法Lispとは何なのか - 同図像性がもたらす力とその利用法
Lispとは何なのか - 同図像性がもたらす力とその利用法
 
何となく勉強した気分になれるパーサ入門
何となく勉強した気分になれるパーサ入門何となく勉強した気分になれるパーサ入門
何となく勉強した気分になれるパーサ入門
 
GraalVMのJavaネイティブビルド機能でどの程度起動が速くなるのか?~サーバレス基盤上での評価~ / How fast does GraalVM's...
GraalVMのJavaネイティブビルド機能でどの程度起動が速くなるのか?~サーバレス基盤上での評価~ / How fast does GraalVM's...GraalVMのJavaネイティブビルド機能でどの程度起動が速くなるのか?~サーバレス基盤上での評価~ / How fast does GraalVM's...
GraalVMのJavaネイティブビルド機能でどの程度起動が速くなるのか?~サーバレス基盤上での評価~ / How fast does GraalVM's...
 
Linuxにて複数のコマンドを並列実行(同時実行数の制限付き)
Linuxにて複数のコマンドを並列実行(同時実行数の制限付き)Linuxにて複数のコマンドを並列実行(同時実行数の制限付き)
Linuxにて複数のコマンドを並列実行(同時実行数の制限付き)
 
実践イカパケット解析
実践イカパケット解析実践イカパケット解析
実践イカパケット解析
 
世界一わかりやすいClean Architecture
世界一わかりやすいClean Architecture世界一わかりやすいClean Architecture
世界一わかりやすいClean Architecture
 
ドメインロジックに集中せよ 〜ドメイン駆動設計 powered by Spring
ドメインロジックに集中せよ 〜ドメイン駆動設計 powered by Springドメインロジックに集中せよ 〜ドメイン駆動設計 powered by Spring
ドメインロジックに集中せよ 〜ドメイン駆動設計 powered by Spring
 
TRICK 2022 Results
TRICK 2022 ResultsTRICK 2022 Results
TRICK 2022 Results
 
トランザクションの設計と進化
トランザクションの設計と進化トランザクションの設計と進化
トランザクションの設計と進化
 
OSS についてあれこれ
OSS についてあれこれOSS についてあれこれ
OSS についてあれこれ
 
Pythonによる黒魔術入門
Pythonによる黒魔術入門Pythonによる黒魔術入門
Pythonによる黒魔術入門
 
JAVA_HOME/binにあるコマンド、いくつ使っていますか?[JVM関連ツール編](JJUGナイトセミナー「Java解析ツール特集」 発表資料)
JAVA_HOME/binにあるコマンド、いくつ使っていますか?[JVM関連ツール編](JJUGナイトセミナー「Java解析ツール特集」 発表資料)JAVA_HOME/binにあるコマンド、いくつ使っていますか?[JVM関連ツール編](JJUGナイトセミナー「Java解析ツール特集」 発表資料)
JAVA_HOME/binにあるコマンド、いくつ使っていますか?[JVM関連ツール編](JJUGナイトセミナー「Java解析ツール特集」 発表資料)
 

Similar a Ruby で高速なプログラムを書く

ETロボコン2020 競技会場システムのおはなし
ETロボコン2020 競技会場システムのおはなしETロボコン2020 競技会場システムのおはなし
ETロボコン2020 競技会場システムのおはなしTetsuya Odashima
 
Play framework 2.0のおすすめと1.2からのアップグレード
Play framework 2.0のおすすめと1.2からのアップグレードPlay framework 2.0のおすすめと1.2からのアップグレード
Play framework 2.0のおすすめと1.2からのアップグレードKazuhiro Hara
 
Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2
Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2
Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2tamtam180
 
Getting Started GraalVM (再アップロード)
Getting Started GraalVM (再アップロード)Getting Started GraalVM (再アップロード)
Getting Started GraalVM (再アップロード)tamtam180
 
Asakusa バッチの運用を支える技術
Asakusa バッチの運用を支える技術Asakusa バッチの運用を支える技術
Asakusa バッチの運用を支える技術KinebuchiTomo
 
アカツキはどのようにAWSを活用しているか #jawsug
アカツキはどのようにAWSを活用しているか #jawsugアカツキはどのようにAWSを活用しているか #jawsug
アカツキはどのようにAWSを活用しているか #jawsugaktsk
 
Gitと出会って人生変わった テックヒルズ2013-03-22
Gitと出会って人生変わった テックヒルズ2013-03-22Gitと出会って人生変わった テックヒルズ2013-03-22
Gitと出会って人生変わった テックヒルズ2013-03-22Shota Umeda
 
2012-03-08 MSS研究会
2012-03-08 MSS研究会2012-03-08 MSS研究会
2012-03-08 MSS研究会Kimikazu Kato
 
明日使える超高速Ruby - RXbyak (Mitaka.rb #5)
明日使える超高速Ruby - RXbyak (Mitaka.rb #5)明日使える超高速Ruby - RXbyak (Mitaka.rb #5)
明日使える超高速Ruby - RXbyak (Mitaka.rb #5)Shuyo Nakatani
 
ピクサー USD 入門 新たなコンテンツパイプラインを構築する
ピクサー USD 入門 新たなコンテンツパイプラインを構築するピクサー USD 入門 新たなコンテンツパイプラインを構築する
ピクサー USD 入門 新たなコンテンツパイプラインを構築するTakahito Tejima
 
Craft CMSに最適なサーバはどんな環境?
Craft CMSに最適なサーバはどんな環境?Craft CMSに最適なサーバはどんな環境?
Craft CMSに最適なサーバはどんな環境?Kei Mikage
 
Web socket and gRPC
Web socket and gRPCWeb socket and gRPC
Web socket and gRPCTIS Inc
 
高速な暗号実装のためにしてきたこと
高速な暗号実装のためにしてきたこと高速な暗号実装のためにしてきたこと
高速な暗号実装のためにしてきたことMITSUNARI Shigeo
 
Web時代の大富豪的プログラミングのススメ
Web時代の大富豪的プログラミングのススメWeb時代の大富豪的プログラミングのススメ
Web時代の大富豪的プログラミングのススメHideyuki Takeuchi
 
Javaはどのように動くのか~スライドでわかるJVMの仕組み
Javaはどのように動くのか~スライドでわかるJVMの仕組みJavaはどのように動くのか~スライドでわかるJVMの仕組み
Javaはどのように動くのか~スライドでわかるJVMの仕組みChihiro Ito
 
openFrameworks Workshop in Kanazawa v001
openFrameworks Workshop in Kanazawa v001openFrameworks Workshop in Kanazawa v001
openFrameworks Workshop in Kanazawa v001Teruaki Tsubokura
 

Similar a Ruby で高速なプログラムを書く (20)

ETロボコン2020 競技会場システムのおはなし
ETロボコン2020 競技会場システムのおはなしETロボコン2020 競技会場システムのおはなし
ETロボコン2020 競技会場システムのおはなし
 
Play framework 2.0のおすすめと1.2からのアップグレード
Play framework 2.0のおすすめと1.2からのアップグレードPlay framework 2.0のおすすめと1.2からのアップグレード
Play framework 2.0のおすすめと1.2からのアップグレード
 
らくちん Go言語
らくちん Go言語らくちん Go言語
らくちん Go言語
 
Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2
Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2
Getting Started GraalVM / GraalVM超入門 #jjug_ccc #ccc_c2
 
Getting Started GraalVM (再アップロード)
Getting Started GraalVM (再アップロード)Getting Started GraalVM (再アップロード)
Getting Started GraalVM (再アップロード)
 
Play jjug2012spring
Play jjug2012springPlay jjug2012spring
Play jjug2012spring
 
Zynga
ZyngaZynga
Zynga
 
Aws privte20110406 arai
Aws privte20110406 araiAws privte20110406 arai
Aws privte20110406 arai
 
Asakusa バッチの運用を支える技術
Asakusa バッチの運用を支える技術Asakusa バッチの運用を支える技術
Asakusa バッチの運用を支える技術
 
アカツキはどのようにAWSを活用しているか #jawsug
アカツキはどのようにAWSを活用しているか #jawsugアカツキはどのようにAWSを活用しているか #jawsug
アカツキはどのようにAWSを活用しているか #jawsug
 
Gitと出会って人生変わった テックヒルズ2013-03-22
Gitと出会って人生変わった テックヒルズ2013-03-22Gitと出会って人生変わった テックヒルズ2013-03-22
Gitと出会って人生変わった テックヒルズ2013-03-22
 
2012-03-08 MSS研究会
2012-03-08 MSS研究会2012-03-08 MSS研究会
2012-03-08 MSS研究会
 
明日使える超高速Ruby - RXbyak (Mitaka.rb #5)
明日使える超高速Ruby - RXbyak (Mitaka.rb #5)明日使える超高速Ruby - RXbyak (Mitaka.rb #5)
明日使える超高速Ruby - RXbyak (Mitaka.rb #5)
 
ピクサー USD 入門 新たなコンテンツパイプラインを構築する
ピクサー USD 入門 新たなコンテンツパイプラインを構築するピクサー USD 入門 新たなコンテンツパイプラインを構築する
ピクサー USD 入門 新たなコンテンツパイプラインを構築する
 
Craft CMSに最適なサーバはどんな環境?
Craft CMSに最適なサーバはどんな環境?Craft CMSに最適なサーバはどんな環境?
Craft CMSに最適なサーバはどんな環境?
 
Web socket and gRPC
Web socket and gRPCWeb socket and gRPC
Web socket and gRPC
 
高速な暗号実装のためにしてきたこと
高速な暗号実装のためにしてきたこと高速な暗号実装のためにしてきたこと
高速な暗号実装のためにしてきたこと
 
Web時代の大富豪的プログラミングのススメ
Web時代の大富豪的プログラミングのススメWeb時代の大富豪的プログラミングのススメ
Web時代の大富豪的プログラミングのススメ
 
Javaはどのように動くのか~スライドでわかるJVMの仕組み
Javaはどのように動くのか~スライドでわかるJVMの仕組みJavaはどのように動くのか~スライドでわかるJVMの仕組み
Javaはどのように動くのか~スライドでわかるJVMの仕組み
 
openFrameworks Workshop in Kanazawa v001
openFrameworks Workshop in Kanazawa v001openFrameworks Workshop in Kanazawa v001
openFrameworks Workshop in Kanazawa v001
 

Más de mametter

error_highlight: User-friendly Error Diagnostics
error_highlight: User-friendly Error Diagnosticserror_highlight: User-friendly Error Diagnostics
error_highlight: User-friendly Error Diagnosticsmametter
 
クックパッド春の超絶技巧パンまつり 超絶技巧プログラミング編 資料
クックパッド春の超絶技巧パンまつり 超絶技巧プログラミング編 資料クックパッド春の超絶技巧パンまつり 超絶技巧プログラミング編 資料
クックパッド春の超絶技巧パンまつり 超絶技巧プログラミング編 資料mametter
 
Enjoy Ruby Programming in IDE and TypeProf
Enjoy Ruby Programming in IDE and TypeProfEnjoy Ruby Programming in IDE and TypeProf
Enjoy Ruby Programming in IDE and TypeProfmametter
 
TypeProf for IDE: Enrich Development Experience without Annotations
TypeProf for IDE: Enrich Development Experience without AnnotationsTypeProf for IDE: Enrich Development Experience without Annotations
TypeProf for IDE: Enrich Development Experience without Annotationsmametter
 
Ruby 3の型解析に向けた計画
Ruby 3の型解析に向けた計画Ruby 3の型解析に向けた計画
Ruby 3の型解析に向けた計画mametter
 
emruby: ブラウザで動くRuby
emruby: ブラウザで動くRubyemruby: ブラウザで動くRuby
emruby: ブラウザで動くRubymametter
 
Type Profiler: Ambitious Type Inference for Ruby 3
Type Profiler: Ambitious Type Inference for Ruby 3Type Profiler: Ambitious Type Inference for Ruby 3
Type Profiler: Ambitious Type Inference for Ruby 3mametter
 
型プロファイラ:抽象解釈に基づくRuby 3の静的解析
型プロファイラ:抽象解釈に基づくRuby 3の静的解析型プロファイラ:抽象解釈に基づくRuby 3の静的解析
型プロファイラ:抽象解釈に基づくRuby 3の静的解析mametter
 
Ruby 3の型推論やってます
Ruby 3の型推論やってますRuby 3の型推論やってます
Ruby 3の型推論やってますmametter
 
マニアックなRuby 2.7新機能紹介
マニアックなRuby 2.7新機能紹介マニアックなRuby 2.7新機能紹介
マニアックなRuby 2.7新機能紹介mametter
 
A Static Type Analyzer of Untyped Ruby Code for Ruby 3
A Static Type Analyzer of Untyped Ruby Code for Ruby 3A Static Type Analyzer of Untyped Ruby Code for Ruby 3
A Static Type Analyzer of Untyped Ruby Code for Ruby 3mametter
 
A Plan towards Ruby 3 Types
A Plan towards Ruby 3 TypesA Plan towards Ruby 3 Types
A Plan towards Ruby 3 Typesmametter
 
Ruby 3 の型解析に向けた計画
Ruby 3 の型解析に向けた計画Ruby 3 の型解析に向けた計画
Ruby 3 の型解析に向けた計画mametter
 
A Type-level Ruby Interpreter for Testing and Understanding
A Type-level Ruby Interpreter for Testing and UnderstandingA Type-level Ruby Interpreter for Testing and Understanding
A Type-level Ruby Interpreter for Testing and Understandingmametter
 
本番環境で使える実行コード記録機能
本番環境で使える実行コード記録機能本番環境で使える実行コード記録機能
本番環境で使える実行コード記録機能mametter
 
Transcendental Programming in Ruby
Transcendental Programming in RubyTranscendental Programming in Ruby
Transcendental Programming in Rubymametter
 
Cookpad Hackarade #04: Create Your Own Interpreter
Cookpad Hackarade #04: Create Your Own InterpreterCookpad Hackarade #04: Create Your Own Interpreter
Cookpad Hackarade #04: Create Your Own Interpretermametter
 
Ruby 3のキーワード引数について考える
Ruby 3のキーワード引数について考えるRuby 3のキーワード引数について考える
Ruby 3のキーワード引数について考えるmametter
 
TRICK 2018 results
TRICK 2018 resultsTRICK 2018 results
TRICK 2018 resultsmametter
 
Type Profiler: An Analysis to guess type signatures
Type Profiler: An Analysis to guess type signaturesType Profiler: An Analysis to guess type signatures
Type Profiler: An Analysis to guess type signaturesmametter
 

Más de mametter (20)

error_highlight: User-friendly Error Diagnostics
error_highlight: User-friendly Error Diagnosticserror_highlight: User-friendly Error Diagnostics
error_highlight: User-friendly Error Diagnostics
 
クックパッド春の超絶技巧パンまつり 超絶技巧プログラミング編 資料
クックパッド春の超絶技巧パンまつり 超絶技巧プログラミング編 資料クックパッド春の超絶技巧パンまつり 超絶技巧プログラミング編 資料
クックパッド春の超絶技巧パンまつり 超絶技巧プログラミング編 資料
 
Enjoy Ruby Programming in IDE and TypeProf
Enjoy Ruby Programming in IDE and TypeProfEnjoy Ruby Programming in IDE and TypeProf
Enjoy Ruby Programming in IDE and TypeProf
 
TypeProf for IDE: Enrich Development Experience without Annotations
TypeProf for IDE: Enrich Development Experience without AnnotationsTypeProf for IDE: Enrich Development Experience without Annotations
TypeProf for IDE: Enrich Development Experience without Annotations
 
Ruby 3の型解析に向けた計画
Ruby 3の型解析に向けた計画Ruby 3の型解析に向けた計画
Ruby 3の型解析に向けた計画
 
emruby: ブラウザで動くRuby
emruby: ブラウザで動くRubyemruby: ブラウザで動くRuby
emruby: ブラウザで動くRuby
 
Type Profiler: Ambitious Type Inference for Ruby 3
Type Profiler: Ambitious Type Inference for Ruby 3Type Profiler: Ambitious Type Inference for Ruby 3
Type Profiler: Ambitious Type Inference for Ruby 3
 
型プロファイラ:抽象解釈に基づくRuby 3の静的解析
型プロファイラ:抽象解釈に基づくRuby 3の静的解析型プロファイラ:抽象解釈に基づくRuby 3の静的解析
型プロファイラ:抽象解釈に基づくRuby 3の静的解析
 
Ruby 3の型推論やってます
Ruby 3の型推論やってますRuby 3の型推論やってます
Ruby 3の型推論やってます
 
マニアックなRuby 2.7新機能紹介
マニアックなRuby 2.7新機能紹介マニアックなRuby 2.7新機能紹介
マニアックなRuby 2.7新機能紹介
 
A Static Type Analyzer of Untyped Ruby Code for Ruby 3
A Static Type Analyzer of Untyped Ruby Code for Ruby 3A Static Type Analyzer of Untyped Ruby Code for Ruby 3
A Static Type Analyzer of Untyped Ruby Code for Ruby 3
 
A Plan towards Ruby 3 Types
A Plan towards Ruby 3 TypesA Plan towards Ruby 3 Types
A Plan towards Ruby 3 Types
 
Ruby 3 の型解析に向けた計画
Ruby 3 の型解析に向けた計画Ruby 3 の型解析に向けた計画
Ruby 3 の型解析に向けた計画
 
A Type-level Ruby Interpreter for Testing and Understanding
A Type-level Ruby Interpreter for Testing and UnderstandingA Type-level Ruby Interpreter for Testing and Understanding
A Type-level Ruby Interpreter for Testing and Understanding
 
本番環境で使える実行コード記録機能
本番環境で使える実行コード記録機能本番環境で使える実行コード記録機能
本番環境で使える実行コード記録機能
 
Transcendental Programming in Ruby
Transcendental Programming in RubyTranscendental Programming in Ruby
Transcendental Programming in Ruby
 
Cookpad Hackarade #04: Create Your Own Interpreter
Cookpad Hackarade #04: Create Your Own InterpreterCookpad Hackarade #04: Create Your Own Interpreter
Cookpad Hackarade #04: Create Your Own Interpreter
 
Ruby 3のキーワード引数について考える
Ruby 3のキーワード引数について考えるRuby 3のキーワード引数について考える
Ruby 3のキーワード引数について考える
 
TRICK 2018 results
TRICK 2018 resultsTRICK 2018 results
TRICK 2018 results
 
Type Profiler: An Analysis to guess type signatures
Type Profiler: An Analysis to guess type signaturesType Profiler: An Analysis to guess type signatures
Type Profiler: An Analysis to guess type signatures
 

Ruby で高速なプログラムを書く