Skip to content

Instantly share code, notes, and snippets.

@wanabe
wanabe / img.inst_retired.any.png
Last active November 5, 2018 00:52
キャッシュがどうパフォーマンスに関わってくるか実例を見たけどまったくわからなかった話

この文章は

以前書いた(というかまだ書いている)キャッシュについてあまりにも何も知らなすぎたのでゼロから調べ直す を下敷きにして、実際に動作を見てキャッシュがどう使われていてどうパフォーマンスに影響しているのかを調べ、たのですが、結局まったくわからなかった、という話です。

MJIT の invokesuper 遅い問題と、その解決

「MJIT の invokesuper 遅い問題」と私が勝手に呼んでいる問題があります。 (というかありました。詳しくは後述)

@wanabe
wanabe / gist:3fc111a4665e60d3e0dc25a6e46a333d
Last active September 12, 2023 11:21
キャッシュについてあまりにも何も知らなすぎたのでゼロから調べ直す

この文章は

題名の通り、私がコンピュータの「キャッシュ」というものについてあまりにも知識不足なため、 ここらで基礎の基礎から調べ直してみて、その結果をまとめるつもりのものです。 たぶんこのテーマだと終わりはないような気がするので、気が向いたときに追加修正していくことになると思います。

キャッシュとは

https://en.oxforddictionaries.com/definition/cache から引用:

  • NOUN
@wanabe
wanabe / gist:90442728ac529ebbaf49cc78ffa691d8
Last active September 20, 2018 00:26
cg_annotate cachegrind.diff
$ cg_annotate cachegrind.diff
--------------------------------------------------------------------------------
Files compared: cachegrind.out.foo; cachegrind.out.bar
Command: ./miniruby --jit --jit-save-temps --jit-verbose=1 -e lv = 20; class A0; def foo; end; def bar; end; end; i = 0; while i < lv; j = i + 1; eval "class A#{j} < A#{i}; def foo; super; end; def bar; super; end; end"; i += 1; end; a = eval("A#{lv}").new; eval "a.foo; " * 5; RubyVM::MJIT.enabled? && RubyVM::MJIT.pause; n = 20_000; i = n; t0 = Time.now; while i > 0; i -= 1; end; i = n; t1 = Time.now; while i > 0; i -= 1; a.foo; end; t2 = Time.now; sec = (t2 - t1 - (t1 - t0)); p n / sec, sec; ./miniruby --jit --jit-save-temps --jit-verbose=1 -e lv = 20; class A0; def foo; end; def bar; end; end; i = 0; while i < lv; j = i + 1; eval "class A#{j} < A#{i}; def foo; super; end; def bar; super; end; end"; i += 1; end; a = eval("A#{lv}").new; eval "a.foo; " * 5; RubyVM::MJIT.enabled? && RubyVM::MJIT.pause; n = 20_000; i = n; t0 = Time.now; w
@wanabe
wanabe / a.rb
Last active September 6, 2018 21:11
MJIT の super の速度確認
max = ARGV[0].to_i
if ARGV[1]
require "rbconfig"
step = ARGV[1].to_i
puts "%4s %13s %13s %13s" % ["n", "jit", "nojit", "rate"]
ruby = RbConfig.ruby
IO.popen("#{ruby} --disable-gems #{__FILE__} #{max}", mode: "r+") do |nojit|
IO.popen("#{ruby} --disable-gems --jit --jit-verbose=1 #{__FILE__} #{max}", mode: "r+") do |jit|
@wanabe
wanabe / 001-gistfile1.md
Last active September 2, 2018 10:53
2018/09/02 時点の trunk の CRuby で MJIT 有効にしたときの Rails のパフォーマンスのネックを探る作業記録

この文章は

https://gist.github.com/wanabe/66642ae87c52f9bebf3d06a4f8c55b43 の続きで、題名の通りの作業記録です。 だいぶしつこいですがまたやります。 例によって例のごとくまったく未完成で書きながら作業しているので、いつ終わるのか何か成果が出るのかわかりません。

とっかかり

CRuby の MJIT は日々進歩しています。 特に、最近 r64094 で追加された "JIT compaction" は MJIT 有効時の Rails の速度改善にかなり効果が高いようです。

@wanabe
wanabe / gist:e758b2e3333355a17791e49444b813eb
Last active July 14, 2018 05:24
MJIT にローカルスタックを取り戻したかったけどうまく行かなかった作業記録

この文章は

2018/07/13 の ruby r63959 現在、MJIT からローカルスタックがなくなっているので、これを復活させたかったのだけどうまく行かなかった、という作業の記録です。 今回は珍しく作業は終えていてあとは文章にまとめるだけになっています。

免責(?)

書き始め当初は、時系列に作業記録を書こうと思っていたのですが、作業当時にメモをつけておらず、作業を再現するだけならできるだろうと思っていたのですが全然できなかったので、「作業記録」というより「作業内容」=「やったこと一覧」になっています。すみませんすみません。

やっぱり作業時にはリアルタイムにメモをとらんといかんと思います。

diff --git a/mjit.c b/mjit.c
index e166a066bf..75dc984ab1 100644
--- a/mjit.c
+++ b/mjit.c
@@ -1290,9 +1290,16 @@ init_header_filename(void)
const size_t libpathflag_len = sizeof(libpathflag) - 1;
#endif
- basedir_val = ruby_prefix_path;
- basedir = StringValuePtr(basedir_val);
@wanabe
wanabe / optcarrot.png
Last active July 2, 2018 00:16
Some benchmark results
$ RBENV=""; for C in `seq 1 1 5`; do RBENV="$RBENV trunk:C=$C" && for BRANCH in trunk+mjit-same-so trunk+mjit-same-so+mjit-iseq-arg; do RBENV="$RBENV $BRANCH,--jit,--jit-min-calls=5000:C=$C:TRAINING_NUM=5000:WAIT_SEC=1"; done; done; RAILS_ENV=production ruby -W0 -S bundle exec rake bench RBENV="$RBENV" DURATION=10|tee bench.log
Booting: production
Endpoint: "/"
Warming up --------------------------------------
bench 998.910 i/s
Calculating -------------------------------------
trunk:C=1 trunk+mjit-same-so,--jit,--jit-min-calls=5000:C=1:TRAINING_NUM=5000:WAIT_SEC=1 trunk+mjit-same-so+mjit-iseq-arg,--jit,--jit-min-calls=5000:C=1:TRAINING_NUM=5000:WAIT_SEC=1 trunk:C=2 trunk+mjit-same-so,--jit,--jit-min-calls=5000:C=2:TRAINING_NUM=5000:WAIT_SEC=1 trunk+mjit-same-so+mjit-iseq-arg,--jit,--jit-min-calls=5000:C=2:TRAINING_NUM=5000:WAIT_SEC=1 trunk:C=3 trunk+mjit-same-so,--jit,--jit-min-calls=5000:C=3:TRAINING_NUM=5000:WAIT_SEC=1 trunk+mjit-same-so+mjit-iseq-arg,--jit,
$ RBENV=""; for C in `ruby -e '10.times {|i| p 2**i}'`; do RBENV="$RBENV trunk+mjit-same-so-mod,--jit,--jit-min-calls=6000,--jit-batch-size=$C:TRAINING_NUM=6000:WAIT_SEC=100:V=1"; done && RAILS_ENV=production ruby -W0 -S bundle exec rake bench RBENV="$RBENV" DURATION=30
Booting: production
Endpoint: "/"
Warming up --------------------------------------
0 bench 5900
0
506.385 i/s
Calculating -------------------------------------
trunk+mjit-same-so-mod,--jit,--jit-min-calls=6000,--jit-batch-size=1,TRAINING_NUM=6000,WAIT_SEC=100,V=1 trunk+mjit-same-so-mod,--jit,--jit-min-calls=6000,--jit-batch-size=2,TRAINING_NUM=6000,WAIT_SEC=100,V=1 trunk+mjit-same-so-mod,--jit,--jit-min-calls=6000,--jit-batch-size=4,TRAINING_NUM=6000,WAIT_SEC=100,V=1 trunk+mjit-same-so-mod,--jit,--jit-min-calls=6000,--jit-batch-size=8,TRAINING_NUM=6000,WAIT_SEC=100,V=1 trunk+mjit-same-so-mod,--jit,--jit-mi
$ RAILS_ENV=production ruby -W0 -S bundle exec rake bench RBENV="trunk trunk,--jit,--jit-min-calls=3000:TRAINING_NUM=3000:WAIT_SEC=100 trunk+mjit-same-so,--jit,--jit-min-calls=3000:TRAINING_NUM=3000:WAIT_SEC=100" DURATION=10
Booting: production
Endpoint: "/"
Warming up --------------------------------------
bench 1.066k i/s
Calculating -------------------------------------
trunk trunk,--jit,--jit-min-calls=3000,TRAINING_NUM=3000,WAIT_SEC=100 trunk+mjit-same-so,--jit,--jit-min-calls=3000,TRAINING_NUM=3000,WAIT_SEC=100
bench 1.031k 594.824 795.382 i/s - 10.663k times in 10.343410s 17.926304s 13.406132s
Comparison: