ruby/ruby — pull request #404 by charliesome (2013-09-28 13:54:59+00:00)
Title: Add rb_funcall_ci

This pull request adds an internal function called `rb_funcall_ci`. This function takes an `rb_call_info_t *` and allows method calls from C to take advantage of method caching.

This gives a large performance improvement when repeatedly calling methods, for example in `Array#sort`.

I used this benchmark script to compare the performance of `Array#sort` when using `rb_funcall` vs. using `rb_funcall_ci`:

```ruby
require "benchmark"

int_ary = (1..1_000_000).to_a.shuffle
float_ary = int_ary.map(&:to_f)

Benchmark.bm do |bm|
5.times do
bm.report "int_ary.sort " do
# uses optimized comparison that does not call any methods
int_ary.sort
end
end
5.times do
bm.report "float_ary.sort" do
# calls Float#<=>
float_ary.sort
end
end
end
```

Results for `rb_funcall`:

```
user system total real
int_ary.sort 0.160000 0.000000 0.160000 ( 0.170144)
int_ary.sort 0.170000 0.000000 0.170000 ( 0.168473)
int_ary.sort 0.170000 0.000000 0.170000 ( 0.169287)
int_ary.sort 0.170000 0.010000 0.180000 ( 0.176867)
int_ary.sort 0.170000 0.000000 0.170000 ( 0.166630)
float_ary.sort 0.910000 0.000000 0.910000 ( 0.911482)
float_ary.sort 0.910000 0.000000 0.910000 ( 0.914818)
float_ary.sort 0.910000 0.000000 0.910000 ( 0.912684)
float_ary.sort 0.920000 0.000000 0.920000 ( 0.915842)
float_ary.sort 0.920000 0.010000 0.930000 ( 0.925721)
```

Results for `rb_funcall_ci`:

```
user system total real
int_ary.sort 0.170000 0.000000 0.170000 ( 0.170202)
int_ary.sort 0.170000 0.000000 0.170000 ( 0.169039)
int_ary.sort 0.170000 0.000000 0.170000 ( 0.168966)
int_ary.sort 0.170000 0.010000 0.180000 ( 0.177495)
int_ary.sort 0.170000 0.000000 0.170000 ( 0.166742)
float_ary.sort 0.680000 0.000000 0.680000 ( 0.683508)
float_ary.sort 0.680000 0.000000 0.680000 ( 0.685977)
float_ary.sort 0.690000 0.000000 0.690000 ( 0.685701)
float_ary.sort 0.690000 0.000000 0.690000 ( 0.692503)
float_ary.sort 0.700000 0.010000 0.710000 ( 0.708043)
```

cc @ko1