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) almost 10 years ago
tenderlove@ruby-lang.org wrote:
I've attached a patch that adds
nilto 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) almost 10 years ago
- Assignee set to ko1 (Koichi Sasada)
Updated by normalperson (Eric Wong) almost 10 years ago
Eric Wong normalperson@yhbt.net wrote:
Cool. Might be worth it to do the same for
trueandfalse,
too, since we have space for them.
Sythetic benchmark shows a 3x speedup on top of r52928:
Updated by Anonymous almost 10 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