Feature #2447
closedreduce GC pressure by symbol table without String instance
Description
=begin
遠藤です。
現在のシンボルテーブルは、シンボルごとに String のインスタンスを
割り当ててシンボル名を管理しますが、そのせいで GC の効率が落ちて
いると思います。
String ではなく ALLOC で直接確保した領域で管理するパッチを書きま
した。極端な例ではこのくらい早くなります。
パッチ前¶
$ time ./ruby.org -e '10000.times { GC.start }; p ObjectSpace.count_objects[:T_STRING]'
1778
real 0m3.766s
user 0m3.764s
sys 0m0.004s
パッチ後¶
$ time ./ruby.new -e '10000.times { GC.start }; p ObjectSpace.count_objects[:T_STRING]'
433
real 0m2.880s
user 0m2.876s
sys 0m0.004s
benchmark 結果は最後にあります。多くのものはほぼ変わらないか速く
なっていると思います。
so_meteor_contest は有意に速度低下しますが (再現性あり) 、理由は
よくわかりません。vm3_thread_mutex は実行する度に実行時間が大きく
変わっていた (3 秒以下から 30 秒超) ので、参考になりませんでした。
どなたか追試してくださると助かります。私の環境で make test-all は
通っています。
1.89s (2.57%): vm2_eval 73.65->71.76
1.88s (2.44%): so_fannkuch 77.14->75.25
1.86s (8.08%): so_partial_sums 23.04->21.18
1.73s (7.20%): so_mandelbrot 23.98->22.26
1.43s (8.68%): so_spectralnorm 16.43->15.00
1.02s (6.19%): so_nbody 16.49->15.47
0.99s (1.13%): app_pentomino 87.50->86.51
0.82s (6.67%): vm1_block 12.23->11.41
0.76s (5.28%): so_nsieve_bits 14.37->13.61
0.51s (15.68%): vm3_gc 3.25->2.74
0.34s (3.16%): so_fasta 10.69->10.35
0.23s (5.13%): so_exception 4.52->4.29
0.22s (3.01%): loop_for 7.45->7.22
0.19s (9.06%): app_raise 2.10->1.91
0.18s (4.67%): so_object 3.88->3.70
0.12s (1.77%): loop_times 6.54->6.42
0.11s (8.49%): so_random 1.31->1.20
0.09s (2.44%): app_uri 3.88->3.78
0.09s (1.07%): vm1_simplereturn 8.35->8.26
0.07s (4.13%): app_strconcat 1.64->1.57
0.06s (0.80%): vm2_mutex 7.33->7.27
0.06s (2.94%): app_erb 1.95->1.89
0.05s (0.59%): vm2_method 8.94->8.89
0.04s (1.04%): vm2_array 3.63->3.59
0.04s (0.97%): vm1_rescue 3.80->3.76
0.03s (0.56%): so_nested_loop 5.88->5.85
0.03s (0.75%): loop_generator 3.83->3.80
0.03s (0.51%): so_pidigits 5.38->5.35
0.03s (2.87%): io_file_read 0.95->0.93
0.03s (0.74%): vm2_proc 3.51->3.48
0.02s (0.65%): vm1_ensure 3.82->3.79
0.02s (1.45%): vm2_poly_method_ov 1.64->1.61
0.02s (0.74%): vm2_zsuper 2.88->2.86
0.02s (2.50%): app_mandelbrot 0.83->0.80
0.02s (0.46%): app_tak 4.36->4.34
0.02s (1.34%): vm2_case 1.24->1.23
0.01s (1.04%): io_file_create 1.18->1.17
0.01s (0.43%): so_matrix 2.11->2.10
0.01s (0.18%): so_ackermann 3.62->3.62
0.01s (0.19%): app_fib 3.21->3.21
0.01s (1.47%): so_sieve 0.41->0.40
0.00s (0.06%): vm1_ivar 6.23->6.22
0.00s (0.03%): so_concatenate 1.91->1.91
0.00s (0.05%): app_factorial 0.66->0.66
0.00s (0.00%): vm1_neq 6.22->6.22
-0.00s (-0.03%): vm2_send 2.02->2.02
-0.00s (-0.41%): app_answer 0.24->0.25
-0.00s (-1.53%): so_reverse_complement 0.09->0.09
-0.00s (-1.96%): so_k_nucleotide 0.07->0.07
-0.00s (-0.38%): io_file_write 0.44->0.44
-0.00s (-0.11%): loop_whileloop 3.38->3.39
-0.00s (-0.13%): app_tarai 3.51->3.51
-0.01s (-0.64%): so_count_words 1.09->1.10
-0.01s (-0.68%): so_lists 1.68->1.69
-0.02s (-2.50%): loop_whileloop2 0.67->0.68
-0.02s (-1.04%): vm2_unif1 1.76->1.78
-0.02s (-1.12%): so_binary_trees 1.81->1.83
-0.03s (-1.10%): vm2_super 2.75->2.78
-0.03s (-0.56%): vm1_const 5.80->5.83
-0.05s (-0.70%): vm2_regexp 6.55->6.59
-0.05s (-0.51%): vm3_thread_create_join 10.49->10.55
-0.06s (-1.18%): vm1_swap 5.18->5.24
-0.11s (-2.21%): vm1_not 4.91->5.02
-0.14s (-1.19%): vm2_poly_method 11.83->11.97
-0.14s (-2.11%): vm1_length 6.64->6.78
-0.15s (-2.33%): vm1_ivar_set 6.57->6.72
-0.18s (-2.42%): so_array 7.40->7.58
-0.31s (-2.23%): so_nsieve 13.79->14.10
-2.22s (-8.38%): so_meteor_contest 26.50->28.72
-26.20s (-177.28%): vm3_thread_mutex 14.78->40.99
--
Yusuke Endoh mame@tsg.ne.jp
=end
Files
Updated by matz (Yukihiro Matsumoto) about 15 years ago
=begin
まつもと ゆきひろです
In message "Re: [ruby-dev:39846] [Bug #2447] reduce GC pressure by symbol table without String instance"
on Sun, 6 Dec 2009 23:24:59 +0900, Yusuke Endoh redmine@ruby-lang.org writes:
|現在のシンボルテーブルは、シンボルごとに String のインスタンスを
|割り当ててシンボル名を管理しますが、そのせいで GC の効率が落ちて
|いると思います。
|
|String ではなく ALLOC で直接確保した領域で管理するパッチを書きま
|した。極端な例ではこのくらい早くなります。
確かに。実はSymbolをGCの対象としようとする伏線で現状のように
なっているのですが、思ったより難しくて放置してます。当面、
SymbolのGCはできそうにないんだから、遠藤さんの指摘のようにす
べきなのかなあ。
=end
Updated by wanabe (_ wanabe) about 15 years ago
=begin
ワナベと申します。
09/12/06 Yusuke Endoh redmine@ruby-lang.org:
現在のシンボルテーブルは、シンボルごとに String のインスタンスを
割り当ててシンボル名を管理しますが、そのせいで GC の効率が落ちて
いると思います。String ではなく ALLOC で直接確保した領域で管理するパッチを書きま
した。極端な例ではこのくらい早くなります。
(中略)
どなたか追試してくださると助かります。私の環境で make test-all は
通っています。
興味がありますので試してみたところ、
少し不思議な結果になりましたので報告させていただきます。
詳細はわかりませんが、環境が貧弱であることが関係していると思われます。
生のベンチマーク結果を末尾に添付します。
そのうち大きく差があったものについて、改めて再現性を調べました。
-
速くなったもの、再現性あり
app_pentomino : 185 - 187 秒 => 182 - 183 秒
so_fannkuch : 194 - 195 秒 => 191 - 192 秒
so_mandelbrot : 56.1 - 56.3 秒 => 48.2 - 48.3 秒
so_nbody : 39.2 - 39.5 秒 => 34.4 - 35.0 秒
so_partial_sums : 54.3 - 54.5 秒 => 47.0 - 47.0 秒
so_spectralnorm : 39.4 - 39.6 秒 => 35.4 - 35.5 秒
vm1_block* : 28.5 - 29.5 秒 => 22.5 - 22.8 秒
vm1_const* : 6.4 - 6.6 秒 => 5.5 - 5.5 秒
vm1_not* : 5.6 - 5.8 秒 => 4.1 - 4.2 秒
vm3_gc : 10.4 - 10.5 秒 => 9.0 - 9.0 秒 -
遅くなったもの、再現性あり
loop_whileloop2 : 17.0 - 17.5 秒 => 18.0 - 18.5 秒
so_ackermann : 8.6 - 8.7 秒 => 8.7 - 8.9 秒
so_exception : 11.8 - 12.2 秒 => 12.8 - 13.4 秒
so_meteor_contest : 46.4 - 48.8 秒 => 50.4 - 51.2 秒
so_reverse_complement : 388 - 389 秒 => 391 - 392 秒
vm2_eval* : 195 - 198 秒 => 206 - 207 秒 -
生データでは変化があったが、再現性のないもの
app_tak : パッチ前後ともに 10.5 - 11.2 秒
io_file_read : パッチ前後ともに 39 - 42 秒
loop_generator : パッチ前後ともに 5.6 - 6.2 秒
loop_times : パッチ前後ともに 14.1 - 14.5 秒
so_count_words : パッチ前後ともに 2 - 5 秒
so_array : パッチ前後ともに 13 - 19 秒
so_sieve : パッチ前後ともに 1.3 - 4.2 秒
benchmark results:
name ruby 1.9.2dev (2009-12-06 trunk 26029) [i386-mingw32] ruby
1.9.2dev (2009-12-06 trunk 26029) [i386-mingw32]
app_answer 0.766 0.797
app_erb 4.484 4.422
app_factorial 2.500 2.641
app_fib 7.797 7.984
app_mandelbrot 2.125 2.172
app_pentomino 187.578 183.078
app_raise 5.422 5.438
app_strconcat 3.313 3.172
app_tak 10.547 11.141
app_tarai 9.203 9.313
app_uri 8.828 8.391
io_file_create 33.641 32.641
io_file_read 39.219 42.203
io_file_write 28.719 28.578
loop_for 15.875 15.875
loop_generator 5.719 6.125
loop_times 13.984 14.328
loop_whileloop 8.125 8.156
loop_whileloop2 1.734 1.844
so_ackermann 8.672 8.781
so_array 19.031 13.938
so_binary_trees 3.906 4.016
so_concatenate 3.719 3.813
so_count_words 5.734 6.844
so_exception 12.047 13.203
so_fannkuch 195.047 191.688
so_fasta 25.000 24.891
so_k_nucleotide 16.469 16.797
so_lists 3.453 3.406
so_mandelbrot 56.344 48.313
so_matrix 4.172 4.266
so_meteor_contest 46.438 50.484
so_nbody 39.297 34.922
so_nested_loop 11.859 12.031
so_nsieve 28.922 29.125
so_nsieve_bits 27.938 27.281
so_object 9.063 9.656
so_partial_sums 54.563 47.047
so_pidigits 17.578 17.594
so_random 3.609 3.328
so_reverse_complement 387.969 392.344
so_sieve 2.234 1.531
so_spectralnorm 39.375 35.422
vm1_block* 29.516 22.875
vm1_const* 6.438 5.547
vm1_ensure* 2.344 2.250
vm1_ivar* 7.844 7.547
vm1_ivar_set* 7.031 7.000
vm1_length* 8.797 8.594
vm1_neq* 6.547 6.922
vm1_not* 5.688 4.172
vm1_rescue* 2.328 2.250
vm1_simplereturn* 13.078 12.797
vm1_swap* 4.375 4.328
vm2_array* 15.063 15.016
vm2_case* 1.844 1.656
vm2_eval* 195.141 206.078
vm2_method* 19.266 19.016
vm2_mutex* 12.469 12.422
vm2_poly_method* 24.109 24.188
vm2_poly_method_ov* 2.344 2.328
vm2_proc* 5.859 5.844
vm2_regexp* 9.953 9.438
vm2_send* 3.156 2.891
vm2_super* 4.781 4.641
vm2_unif1* 2.813 2.625
vm2_zsuper* 5.500 5.406
vm3_gc 10.531 9.031
vm3_thread_create_join 27.234 27.828
vm3_thread_mutex 3.000 3.188
--
ワナベ
=end
Updated by mame (Yusuke Endoh) about 15 years ago
=begin
遠藤です。
2009年12月8日18:37 wanabe s.wanabe@gmail.com:
どなたか追試してくださると助かります。私の環境で make test-all は
通っています。興味がありますので試してみたところ、
少し不思議な結果になりましたので報告させていただきます。
詳細はわかりませんが、環境が貧弱であることが関係していると思われます。生のベンチマーク結果を末尾に添付します。
そのうち大きく差があったものについて、改めて再現性を調べました。
とても詳しい追試、ありがとうございます。
- 速くなったもの、再現性あり
app_pentomino : 185 - 187 秒 => 182 - 183 秒
so_fannkuch : 194 - 195 秒 => 191 - 192 秒
so_mandelbrot : 56.1 - 56.3 秒 => 48.2 - 48.3 秒
so_nbody : 39.2 - 39.5 秒 => 34.4 - 35.0 秒
so_partial_sums : 54.3 - 54.5 秒 => 47.0 - 47.0 秒
so_spectralnorm : 39.4 - 39.6 秒 => 35.4 - 35.5 秒
vm1_block* : 28.5 - 29.5 秒 => 22.5 - 22.8 秒
vm1_const* : 6.4 - 6.6 秒 => 5.5 - 5.5 秒
vm1_not* : 5.6 - 5.8 秒 => 4.1 - 4.2 秒
vm3_gc : 10.4 - 10.5 秒 => 9.0 - 9.0 秒
それぞれ 2% 、2% 、14% 、12% 、14% 、10% 、21% 、15% 、27% 、13%
くらいの高速化ですね。
- 遅くなったもの、再現性あり
loop_whileloop2 : 17.0 - 17.5 秒 => 18.0 - 18.5 秒
so_ackermann : 8.6 - 8.7 秒 => 8.7 - 8.9 秒
so_exception : 11.8 - 12.2 秒 => 12.8 - 13.4 秒
so_meteor_contest : 46.4 - 48.8 秒 => 50.4 - 51.2 秒
so_reverse_complement : 388 - 389 秒 => 391 - 392 秒
vm2_eval* : 195 - 198 秒 => 206 - 207 秒
-6% 、-2% 、-9% 、-7% 、-1% 、-5% くらいですね。
総じて言えば、速くなっていると言えるのではないかと思います。
どうでしょうか。
--
Yusuke ENDOH mame@tsg.ne.jp
=end
Updated by mame (Yusuke Endoh) over 14 years ago
Updated by shyouhei (Shyouhei Urabe) over 14 years ago
- Status changed from Open to Assigned
=begin
=end
Updated by ko1 (Koichi Sasada) over 12 years ago
- Description updated (diff)
あれ,これ私ですか.
ええと,今度やります.これは,big feature じゃないから遅くてもいいよね.
Updated by mame (Yusuke Endoh) over 12 years ago
明らかに feature request なので移動します。
自分へのツッコミですが、「明らかに bug ではない」が正確ですね。
こういう最適化みたいに、ユーザが直接観察できない改善は、feature request deadline 後でもいいと思います。
ただ、(時期は決めてなかったと思いますが) code freeze 後ではダメだし、branch を切った後でも面倒になると思うので、なるべく早めにやってください。
--
Yusuke Endoh mame@tsg.ne.jp
Updated by ko1 (Koichi Sasada) about 12 years ago
- Assignee changed from ko1 (Koichi Sasada) to mame (Yusuke Endoh)
すみません,「やります」と書いておきながら,全然覚えてないんですが,
私はとくに反論ないので(テストが通るなら),遠藤さん入れちゃいませんか?
Updated by mame (Yusuke Endoh) about 12 years ago
- Priority changed from Normal to 3
うーん、他の作業がすべて終わったあとで気力があればやります。ないかも
--
Yusuke Endoh mame@tsg.ne.jp
Updated by mame (Yusuke Endoh) about 12 years ago
- Target version changed from 2.0.0 to 2.6
他にやってくれる人がいなければ next minor 送りで。
--
Yusuke Endoh mame@tsg.ne.jp
Updated by naruse (Yui NARUSE) about 7 years ago
- Status changed from Assigned to Rejected
これもうobsoleteですよね
Updated by mame (Yusuke Endoh) about 7 years ago
- Status changed from Rejected to Assigned
パッチ自体は適用不能だと思いますが、全シンボルに対応する文字列オブジェクトはいまでも作られているので、最適化の選択肢として残ってるという認識です。効果は減ってるかもしれませんが。
近いうちに検証したいと思っていたのでしばらく残しておいてもらっていいですか。(数年放置のフラグ)
Updated by mame (Yusuke Endoh) almost 6 years ago
- Status changed from Assigned to Rejected
ささださんと相談しました。
- 世代別 GC がある現在ではおそらく効果は弱いだろう
- Symbol GC が導入されたので、同じことをやると結構複雑になりそう(エントリの削除に対応しないといけない)
ということで、たぶんペイしないだろう、という推定になったので、閉じておきます。