Railsプルリクのぞき見 - 2018/10/10
RubyやRailsにちょっとでも貢献したいんですが、まだまだ若輩者なのでRubyやRailsのプルリクなどを半年ROMっていようかと。
継続できるように、雑に眺めて内容がわかったものをピックアップして紹介してみる。
nilClassのtryを高速化
メソッドの引数定義を def try(*args)
から def try(method_name = nil, *args)
ってするだけで処理速度が上がるみたい。
nilClassだけなのはなんでかな?と思ったら、他のクラスは元々第一引数を method_name
としてあったんですねー。nilClassはどうせnil返すだけで引数使わないからって*args
だけにしてたらRubyがメソッド呼び出すのに時間がかかってしまうようですね。
Rubyがメソッドの可変長引数を解釈しているところはどこだろう。そのコードまで追えるかな...
Rubyでの引数の扱い
↑の記事によると、Rubyには8種類の引数(パラメーター)がある。
Rubyの中では↓の構造体で表現しているもよう。
struct args_info { /* basic args info */ VALUE *argv; int argc; const struct rb_call_info_kw_arg *kw_arg; /* additional args info */ int rest_index; VALUE *kw_argv; VALUE rest; };
ruby/vm_args.c at ruby_2_5 · ruby/ruby · GitHub
たぶん、argv
argc
が必須な引数を表していて、kw_argv
はキーワード引数だろうから、rest
がsplat部分かな。
同ファイルの setup_parameters_complex
っていう関数でなんかごにょごにょしてるあたりかなー。
if (iseq->body->param.flags.has_opt) { int opt = args_setup_opt_parameters(args, iseq->body->param.opt_num, locals + iseq->body->param.lead_num); opt_pc = (int)iseq->body->param.opt_table[opt]; } if (iseq->body->param.flags.has_rest) { args_setup_rest_parameter(args, locals + iseq->body->param.rest_start); }
args_setup_rest_parameter
の中でarg_copy
関数使ってsplatパラメーターをコピーしたりしてるっぽい。
ということは、def try(*args)
にたいして xxx.try(:hoge)
と呼び出すと引数データのコピーとかが実行されるってことかな。
それを def try(:method_name = nil, *args)
にするとargs_setup_opt_parameters
の方が使われて、そのなかではコピーはしてせずにargv
argc
にセットしているもよう。
っていう感じで実行速度に差がでる... ってことでいいのかな?