mirror of
https://github.com/ruby/ruby.git
synced 2025-08-15 13:39:04 +02:00
use inline cache for refinements
From Ruby 3.0, refined method invocations are slow because resolved methods are not cached by inline cache because of conservertive strategy. However, `using` clears all caches so that it seems safe to cache resolved method entries. This patch caches resolved method entries in inline cache and clear all of inline method caches when `using` is called. fix [Bug #18572] ```ruby # without refinements class C def foo = :C end N = 1_000_000 obj = C.new require 'benchmark' Benchmark.bm{|x| x.report{N.times{ obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; }} } _END__ user system total real master 0.362859 0.002544 0.365403 ( 0.365424) modified 0.357251 0.000000 0.357251 ( 0.357258) ``` ```ruby # with refinment but without using class C def foo = :C end module R refine C do def foo = :R end end N = 1_000_000 obj = C.new require 'benchmark' Benchmark.bm{|x| x.report{N.times{ obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; }} } __END__ user system total real master 0.957182 0.000000 0.957182 ( 0.957212) modified 0.359228 0.000000 0.359228 ( 0.359238) ``` ```ruby # with using class C def foo = :C end module R refine C do def foo = :R end end N = 1_000_000 using R obj = C.new require 'benchmark' Benchmark.bm{|x| x.report{N.times{ obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; obj.foo; }} }
This commit is contained in:
parent
280419d0e0
commit
cfd7729ce7
Notes:
git
2023-07-31 08:14:03 +00:00
7 changed files with 58 additions and 19 deletions
17
vm_method.c
17
vm_method.c
|
@ -307,19 +307,19 @@ rb_clear_method_cache(VALUE klass_or_module, ID mid)
|
|||
void rb_cc_table_free(VALUE klass);
|
||||
|
||||
static int
|
||||
invalidate_all_cc(void *vstart, void *vend, size_t stride, void *data)
|
||||
invalidate_all_refinement_cc(void *vstart, void *vend, size_t stride, void *data)
|
||||
{
|
||||
VALUE v = (VALUE)vstart;
|
||||
for (; v != (VALUE)vend; v += stride) {
|
||||
void *ptr = asan_poisoned_object_p(v);
|
||||
asan_unpoison_object(v, false);
|
||||
|
||||
if (RBASIC(v)->flags) { // liveness check
|
||||
if (RB_TYPE_P(v, T_CLASS) ||
|
||||
RB_TYPE_P(v, T_ICLASS)) {
|
||||
if (RCLASS_CC_TBL(v)) {
|
||||
rb_cc_table_free(v);
|
||||
if (imemo_type_p(v, imemo_callcache)) {
|
||||
const struct rb_callcache *cc = (const struct rb_callcache *)v;
|
||||
if (vm_cc_refinement_p(cc) && cc->klass) {
|
||||
vm_cc_invalidate(cc);
|
||||
}
|
||||
RCLASS_CC_TBL(v) = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -331,10 +331,9 @@ invalidate_all_cc(void *vstart, void *vend, size_t stride, void *data)
|
|||
}
|
||||
|
||||
void
|
||||
rb_clear_method_cache_all(void)
|
||||
rb_clear_all_refinement_method_cache(void)
|
||||
{
|
||||
rb_objspace_each_objects(invalidate_all_cc, NULL);
|
||||
|
||||
rb_objspace_each_objects(invalidate_all_refinement_cc, NULL);
|
||||
rb_yjit_invalidate_all_method_lookup_assumptions();
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue