aboutsummaryrefslogtreecommitdiffstats
path: root/benchmark
diff options
context:
space:
mode:
authorJean Boussier <jean.boussier@gmail.com>2021-02-12 17:31:19 +0100
committerAaron Patterson <aaron.patterson@gmail.com>2021-03-10 13:43:22 -0800
commita03653d386bd64256932ea7eead3c28f03de1bac (patch)
treef781523dd309618615d615c40371d64710c61417 /benchmark
parentd9fea496afed5a35d2f79ea3cac35176966dd471 (diff)
downloadruby-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.yml16
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