diff options
author | Jean Boussier <jean.boussier@gmail.com> | 2021-02-12 17:31:19 +0100 |
---|---|---|
committer | Aaron Patterson <aaron.patterson@gmail.com> | 2021-03-10 13:43:22 -0800 |
commit | a03653d386bd64256932ea7eead3c28f03de1bac (patch) | |
tree | f781523dd309618615d615c40371d64710c61417 /benchmark | |
parent | d9fea496afed5a35d2f79ea3cac35176966dd471 (diff) | |
download | ruby-a03653d386bd64256932ea7eead3c28f03de1bac.tar.gz |
proc.c: make bind_call use existing callable method entry when possible
The most common use case for `bind_call` is to protect from core
methods being redefined, for instance a typical use:
```ruby
UNBOUND_METHOD_MODULE_NAME = Module.instance_method(:name)
def real_mod_name(mod)
UNBOUND_METHOD_MODULE_NAME.bind_call(mod)
end
```
But it's extremely common that the method wasn't actually redefined.
In such case we can avoid creating a new callable method entry,
and simply delegate to the receiver.
This result in a 1.5-2X speed-up for the fast path, and little to
no impact on the slowpath:
```
compare-ruby: ruby 3.1.0dev (2021-02-05T06:33:00Z master b2674c1fd7) [x86_64-darwin19]
built-ruby: ruby 3.1.0dev (2021-02-15T10:35:17Z bind-call-fastpath d687e06615) [x86_64-darwin19]
| |compare-ruby|built-ruby|
|:---------|-----------:|---------:|
|fastpath | 11.325M| 16.393M|
| | -| 1.45x|
|slowpath | 10.488M| 10.242M|
| | 1.02x| -|
```
Diffstat (limited to 'benchmark')
-rw-r--r-- | benchmark/method_bind_call.yml | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/benchmark/method_bind_call.yml b/benchmark/method_bind_call.yml new file mode 100644 index 0000000000..9e0e046ed4 --- /dev/null +++ b/benchmark/method_bind_call.yml @@ -0,0 +1,16 @@ +prelude: | + named_module = Kernel + + module FakeName + def self.name + "NotMyame".freeze + end + end + + MOD_NAME = Module.instance_method(:name) + +benchmark: + fastpath: MOD_NAME.bind_call(Kernel) + slowpath: MOD_NAME.bind_call(FakeName) + +loop_count: 100_000 |