Project

General

Profile

Actions

Feature #11769

closed

optimize case / when for `nil`

Added by tenderlovemaking (Aaron Patterson) over 8 years ago. Updated over 8 years ago.

Status:
Closed
Target version:
-
[ruby-core:71818]

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

0001-optimize-case-when-for-nil.patch (3.4 KB) 0001-optimize-case-when-for-nil.patch tenderlovemaking (Aaron Patterson), 12/03/2015 09:42 PM

Updated by normalperson (Eric Wong) over 8 years ago

wrote:

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".

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) over 8 years ago

  • Assignee set to ko1 (Koichi Sasada)

Updated by normalperson (Eric Wong) over 8 years ago

Eric Wong wrote:

Cool. Might be worth it to do the same for true and false,
too, since we have space for them.

Sythetic benchmark shows a 3x speedup on top of r52928:

http://80x24.org/spew/20151208001623.2666-1-e@80x24.org/raw

Actions #4

Updated by Anonymous over 8 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
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0