ruby-trunk-changes r52325 - r52355

今日はテストの CI 対策の他文字列の Encoding チェックの高速化やオブジェクト生成時の処理の最適化などがありました。

ngoto: r52325 2015-10-28 23:54:53 +0900

DTrace 対応で hook point を挿入するための関数マクロRUBY_DTRACE_HOOK() で RB_GC_GUARD() を追加しています。 Ruby のコンテキスト切り替えポイントがなさそうなので、多分大丈夫だと思いますけど、まあ念のため。。

naruse: r52326 2015-10-29 00:11:16 +0900

SIGQUIT 受信時のテストのための spawn 前に GC.start を呼ぶようにしています。 CI でのエラーの調査のためみたいですね。

svn: r52327 2015-10-29 00:11:29 +0900

version.h の日付更新。

ngoto: r52328 2015-10-29 00:36:49 +0900

r52312 の rubygems のテストでの Solaris の対応を revert しています。次の 52313 で別の対応を入れてます。

ngoto: r52329 2015-10-29 00:43:27 +0900

r52328 で revert した r52312 のやりなおしです。 Solaris ではデフォルトで /etc/services に http のエントリがないため失敗するので、http ではなくて discard というサービス名を指定してテストするようにしています。
discard は他のプラットフォームに常にあるのか…というところですが http よりも古くて多分大丈夫だろうとのこと。古いのは古いので逆に消えてしまうのではないかという気もしないではないですが…。 [ruby-core:63518] [Bug #10004]

naruse: r52330 2015-10-29 03:58:34 +0900

Thread.handle_interrupt のテストで生成した Thread を後始末で kill して止めるようにしています。

naruse: r52331 2015-10-29 04:03:31 +0900

r52326 で SIGQUIT のテストの spawn 前の GC.start で full_mark: true, immediate_sweep: true オプションを指定して完全に GC 完了させるようにしています。また finalizer 実行中の SIGINT の受信時のテストでも GC を行なってから子プロセスを起動するようにして、またタイムアウトも伸ばしています。メモリサイズが大きい状態での fork の速度の対策とかでしょうか。

normal: r52332 2015-10-29 08:59:45 +0900

autoload を設定した定数への参照を複数 Thread で同時に行なった時にうまくロックができずロードされた定数が見えない状態になることがある不具合の修正です。
これまであった struct autoload_data_i をさらに wrap した struct autoload_state という構造体を導入して、ここに待っている Thread の情報を linked list で持たせて load が終わった thread が明示的に待ってる thread を起こすようになります。 autoload の lock は超むずかしいのですが、追加された部分は比較的わかりやすいですね。 [ruby-core:70075] [ruby-core:71239] [Bug #11384]

normal: r52333 2015-10-29 09:24:48 +0900

r52332 の ChangeLog エントリに記述が漏れていたのを追加しています。

naruse: r52334 2015-10-29 09:44:13 +0900

Thread.handle_interrupt のテストで sleep しているところの時間を 1 -> 0.2 に短くして、また Thread#join で待つ時のタイムアウトが 0 だったので待ててないことがあったのを修正しています。

normal: r52335 2015-10-29 10:14:45 +0900

r52332 で追加した autoload の lock 用の構造体 struct autoload_state が struct autoload_data_i を指すようにしていたのを、struct autoload_data_i から struct autoload_state を指すようにして struct autoload_data_i から thread や link list の head などのメンバを削除して、heap に確保するメモリ領域を減らすように最適化しています。struct autoload_state はマシンスタック上に置かれるのでそちらに寄せるようにしているみたいです。

ko1: r52336 2015-10-29 14:10:06 +0900

gc.c のデバッグ用出力の削除、といっしょに他の修正も混ざってしまったようなので次の r52337 で revert されています。

ko1: r52337 2015-10-29 14:30:50 +0900

余分な変更が混ざってしまった r52336 を revert しています。

nobu: r52338 2015-10-29 14:32:19 +0900

r52325 で RB_GC_GUARD() を追加した関数マクロ RUBY_DTRACE_METHOD_HOOK() ですが引数の準備の部分が長いので ruby_th_dtrace_setup() という関数に切り出してこれを呼ぶようにして定義を短かくしています。 しかしこの関数 inline 化されないように宣言されてますし、probe の挿入部分でオーバヘッドを抑えるために展開されるようにしてたんじゃないかなという気もするのですが、関数呼び出しを入れていいんでしょうか。まあそれを言うなら RB_GC_GUARD() もパフォーマンスへ影響あるかもしれませんが。

ko1: r52339 2015-10-29 14:32:42 +0900

r52336 のやりなおし。 [Bug #11244] の確認のために r51010 や r51018 で追加した gc_mark_ptr() のデバッグメッセージを削っています。

nobu: r52340 2015-10-29 14:32:57 +0900

DTrace の probe 挿入の RUBY_DTRACE_CREATE_HOOK() というマクロを追加して、オブジェクト生成時の probe 追加をこのマクロを利用するようにリファクタリングしています。

nobu: r52341 2015-10-29 14:33:16 +0900

probes.d から probes.h を作る時の guard 用の #ifndef などのマクロ名を置換する時に RUBY_PROBE_H と RUBY_ を prefix につけるようにしています。

nobu: r52342 2015-10-29 14:45:18 +0900

vm_core.h の struct rb_thread_struct と struct rb_control_frame_struct の宣言を前のほうに移動しています。

nobu: r52343 2015-10-29 15:03:17 +0900

デバッグ用の VM のプロファイラ用のカウンタをインクリメントする VM_PROFILE_UP() というマクロでカウンタの種類を指定する番号を直接書いていたのを enum 型で定数として定義してそれを利用するようにリファクタリングしています。また結果を出力する関数で表示しているメッセージの typo 修正。

ko1: r52344 2015-10-29 15:17:07 +0900

rb_objspace::flags に has_hook という bit field を追加して newobj_of() で gc_event_hook() を呼ぶ必要があるかどうかのチェックにこのフラグを参照するようにしてチェックを軽量にしています。その他条件分岐の条件に UNLIKELY() を追加するなど最適化のための変更。

nobu: r52345 2015-10-29 16:21:24 +0900

r52344 で UNLIKELY() を関数マクロ gc_event_hook_needed_p() のビット演算に入れてたのをやめて、呼び元の if の条件部に書くようにしています。これ違うんだ…。また newobj_init() にも hook の有無のチェックの条件に UNLIKELY() を追加しています。

ko1: r52346 2015-10-29 16:26:44 +0900

newobj_of() やそこから呼ばれる関数群に wb_protected という引数を追加して、RGenGC などの write barrier が効いているオブジェクトかどうかを flags から判定させていたのを明示的に引数で渡すように変更して、rb_wb_unprotected_newobj_of() と rb_wb_protected_newobj_of() という関数を導入しています。

ko1: r52347 2015-10-29 16:43:48 +0900

r52346 で追加した rb_wb_protected_newobj_of() と rb_wb_unprotected_newobj_of() に RGENGC_CHECK_MODE が 1以上でコンパイルされた時の struct RBasic::flags との整合性チェックの assert() を追加しています。また rb_imemo_new() で T_IMEMO 型のオブジェクトを生成する時に flags に FL_WB_PROTECTED を立ててましたが削って、newobj_of() の引数で指定するようにしています。

nobu: r52348 2015-10-29 17:00:01 +0900

r52348 のあたりの newobj_of() での GC の hook_events の有無チェックに関連して newobj_init() の hook_needed という引数を削除して gc_event_hook() の呼び出しを newobj_of_slowpath() に移動しています。 fastpath の時に余分な分岐を減らす最適化ですね。

ko1: r52349 2015-10-29 17:17:32 +0900

r52346 で追加した internal.h の rb_wb_protected_newobj_of() と rb_wb_unprotected_newobj_of() を gc.c の (export) とコメント書かれたセクションに移動しています。

ko1: r52350 2015-10-29 18:10:32 +0900

文字列のエンコーディングの互換性のチェックのための関数に rb_enc_check_str() というのを追加して、引数が T_STRING か T_REGEXP だということがわかっている時にチェックやオブジェクトの変換の処理をスキップして直接 encindex を取得する enc_get_index_str() という関数を利用するようにしています。 これは TinySegmenter という日本語の分かち書きのライブラリのベンチマークRuby 版を高速化するために入れた最適化みたいです。

ko1: r52351 2015-10-29 18:48:38 +0900

gc.c の gc_mark_ptr() に NOINLINE() マクロを使って inline 化しないようにしています。gc_mark() は is_markable_object(objspace, obj) が偽の時はすぐ return してこの呼び出しにこないから、と書かれてるんですがそれでなぜ inline すべきでないのかなぁ。 is_markable_object() は要するに即値かどうかの判定みたいなので、すぐに return する率はある程度高いだろうとはいえ rb_mark_ptr() に来るケースもかなりあると思うのですが。 rb_mark_ptr() のコードサイズを小さく保つためかな。

kazu: r52352 2015-10-29 22:01:19 +0900

r52346 の ChangeLog エントリの typo 修正。

nobu: r52355 2015-10-29 23:01:13 +0900

r52350 で encoding.c の一部インデントがずれてしまっていたのと ChangeLog エントリの typo 修正。