Feature #11769
closedoptimize case / when for `nil`
Description
Hi,
I've noticed that when there are certain values in a case / when statement it gets optimized to a hash lookup. For example, code like this:
def foo socket
case str = socket.read_nonblock(10, exception: false)
when :wait_readable
# do something
else
str
end
end
puts RubyVM::InstructionSequence.of(method(:foo)).disasm
The above code will use opt_case_dispatch
instruction with a hash. However, if I use nil
in the case statement like this:
def foo socket
case str = socket.read_nonblock(10, exception: false)
when :wait_readable
# do something
when nil
# got an EOF
else
str
end
end
puts RubyVM::InstructionSequence.of(method(:foo)).disasm
Then the optimization is lost.
I've attached a patch that adds nil
to the optimized case such that the above code will use opt_case_dispatch
. My patch defines ===
on nil
, then adds nil to the list of "optimizable literals".
Files
Updated by normalperson (Eric Wong) about 9 years ago
tenderlove@ruby-lang.org wrote:
I've attached a patch that adds
nil
to the optimized case such that
the above code will useopt_case_dispatch
. My patch defines===
onnil
, then adds nil to the list of "optimizable literals".
Cool. Might be worth it to do the same for true
and false
,
too, since we have space for them.
Updated by ko1 (Koichi Sasada) about 9 years ago
- Assignee set to ko1 (Koichi Sasada)
Updated by normalperson (Eric Wong) about 9 years ago
Eric Wong normalperson@yhbt.net wrote:
Cool. Might be worth it to do the same for
true
andfalse
,
too, since we have space for them.
Sythetic benchmark shows a 3x speedup on top of r52928:
Updated by Anonymous about 9 years ago
- Status changed from Open to Closed
Applied in changeset r52931.
compile optimized case dispatch for nil/true/false
nil/true/false are special literals just like floats, integers,
literal strings, and symbols. Optimize when statements with
them by using a jump table, too.
target 0: a (ruby 2.3.0dev (2015-12-08 trunk 52928) [x86_64-linux]) at "/home/ew/rrrr/b/ruby"
target 1: b (ruby 2.3.0dev (2015-12-08 master 52928) [x86_64-linux]) at "/home/ew/ruby/b/ruby"
benchmark results:
minimum results in each 5 measurements.
Execution time (sec)
name a b
loop_whileloop2 0.102 0.103
vm2_case_lit* 1.657 0.549
Speedup ratio: compare with the result of `a' (greater is better)
name b
loop_whileloop2 0.988
vm2_case_lit* 3.017
- benchmark/bm_vm2_case_lit.rb: new benchmark
- compile.c (case_when_optimizable_literal): add nil/true/false
- insns.def (opt_case_dispatch): ditto
- vm.c (vm_redefinition_check_flag): ditto
- vm.c (vm_init_redefined_flag): ditto
- vm_core.h: ditto
- object.c (InitVM_Object): define === explicitly for nil/true/false
- test/ruby/test_case.rb (test_deoptimize_nil): new test
- test/ruby/test_optimization.rb (test_opt_case_dispatch): update
(test_eqq): new test
[ruby-core:71923] [Feature #11769]
Original patch by Aaron Patterson tenderlove@ruby-lang.org