Feature #2447
reduce GC pressure by symbol table without String instance
| Status: | Assigned | Start date: | 12/06/2009 | |
|---|---|---|---|---|
| Priority: | Normal | Due date: | ||
| Assignee: | % Done: | 0% |
||
| Category: | core | |||
| Target version: | 2.0.0 |
Description
遠藤です。
現在のシンボルテーブルは、シンボルごとに 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>
History
Updated by matz (Yukihiro Matsumoto) over 2 years ago
まつもと ゆきひろです 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はできそうにないんだから、遠藤さんの指摘のようにす べきなのかなあ。
Updated by wanabe (_ wanabe) over 2 years ago
ワナベと申します。 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 -- ワナベ
Updated by mame (Yusuke Endoh) over 2 years ago
遠藤です。 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>
Updated by mame (Yusuke Endoh) about 2 years ago
遠藤です。 明らかに feature request なので移動します。 -- Yusuke Endoh <mame@tsg.ne.jp>
Updated by shyouhei (Shyouhei Urabe) over 1 year ago
- Status changed from Open to Assigned