compile.c: Emit send for === calls in when statements
The checkmatch instruction with VM_CHECKMATCH_TYPE_CASE calls === without a call cache. Emit a send instruction to make the call instead. It includes a call cache. The call cache improves throughput of using when statements to check the class of a given object. This is useful for say, JSON serialization. Use of a regular send instead of checkmatch also avoids taking the VM lock every time, which is good for multi-ractor workloads. Calculating ------------------------------------- master post vm_case_classes 11.013M 16.172M i/s - 6.000M times in 0.544795s 0.371009s vm_case_lit 2.296 2.263 i/s - 1.000 times in 0.435606s 0.441826s vm_case 74.098M 64.338M i/s - 6.000M times in 0.080974s 0.093257s Comparison: vm_case_classes post: 16172114.4 i/s master: 11013316.9 i/s - 1.47x slower vm_case_lit master: 2.3 i/s post: 2.3 i/s - 1.01x slower vm_case master: 74097858.6 i/s post: 64338333.9 i/s - 1.15x slower The vm_case benchmark is a bit slower post patch, possibily due to the larger instruction sequence. The benchmark dispatches using opt_case_dispatch so was not running checkmatch and does not make the === call post patch.
This commit is contained in:
parent
788d30a8b3
commit
5ada23ac12
Notes:
git
2021-05-29 01:34:38 +09:00
9
benchmark/vm_case_classes.yml
Normal file
9
benchmark/vm_case_classes.yml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
benchmark:
|
||||||
|
vm_case_classes: |
|
||||||
|
case :foo
|
||||||
|
when Hash
|
||||||
|
raise
|
||||||
|
when Array
|
||||||
|
raise
|
||||||
|
end
|
||||||
|
loop_count: 6000000
|
@ -4572,8 +4572,6 @@ when_vals(rb_iseq_t *iseq, LINK_ANCHOR *const cond_seq, const NODE *vals,
|
|||||||
rb_hash_aset(literals, lit, (VALUE)(l1) | 1);
|
rb_hash_aset(literals, lit, (VALUE)(l1) | 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
ADD_INSN(cond_seq, val, dup); /* dup target */
|
|
||||||
|
|
||||||
if (nd_type(val) == NODE_STR) {
|
if (nd_type(val) == NODE_STR) {
|
||||||
debugp_param("nd_lit", val->nd_lit);
|
debugp_param("nd_lit", val->nd_lit);
|
||||||
lit = rb_fstring(val->nd_lit);
|
lit = rb_fstring(val->nd_lit);
|
||||||
@ -4584,7 +4582,9 @@ when_vals(rb_iseq_t *iseq, LINK_ANCHOR *const cond_seq, const NODE *vals,
|
|||||||
if (!COMPILE(cond_seq, "when cond", val)) return -1;
|
if (!COMPILE(cond_seq, "when cond", val)) return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ADD_INSN1(cond_seq, vals, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE));
|
// Emit patern === target
|
||||||
|
ADD_INSN1(cond_seq, vals, topn, INT2FIX(1));
|
||||||
|
ADD_CALL(cond_seq, vals, idEqq, INT2FIX(1));
|
||||||
ADD_INSNL(cond_seq, val, branchif, l1);
|
ADD_INSNL(cond_seq, val, branchif, l1);
|
||||||
vals = vals->nd_next;
|
vals = vals->nd_next;
|
||||||
}
|
}
|
||||||
|
@ -497,7 +497,7 @@ class TestJIT < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_compile_insn_checkmatch_opt_case_dispatch
|
def test_compile_insn_checkmatch_opt_case_dispatch
|
||||||
assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '"world"', insns: %i[checkmatch opt_case_dispatch])
|
assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '"world"', insns: %i[opt_case_dispatch])
|
||||||
begin;
|
begin;
|
||||||
case 'hello'
|
case 'hello'
|
||||||
when 'hello'
|
when 'hello'
|
||||||
|
Loading…
x
Reference in New Issue
Block a user