Permalink
Browse files

Improve performance of Range#{min,max}

range.c (range_min): use OPTIMIZED_CMP() to compare the objects instead of
    `<=>' method dispatching for Fixnum/Float/String object inside Range object.

range.c (range_max): ditto.

    Range#min -> 34 % up
    Range#max -> 44 % up

    [ruby-core:80713] [Bug #13443] [Fix GH-1585]

### Before
           Range#min      8.428M (± 1.3%) i/s -     42.141M in   5.000952s
           Range#max      8.157M (± 1.3%) i/s -     40.852M in   5.009297s

### After
           Range#min     11.269M (± 1.2%) i/s -     56.388M in   5.004611s
           Range#max     11.764M (± 1.3%) i/s -     58.856M in   5.003820s

### Test code
require 'benchmark/ips'

Benchmark.ips do |x|
  x.report "Range#min" do |i|
    i.times { (1..100).min }
  end

  x.report "Range#max" do |i|
    i.times { (1..100).max }
  end
end

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@58964 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
  • Loading branch information...
Watson1978 committed May 30, 2017
1 parent afa0e3c commit ab3a40c1031ff3a0535f6bcf26de40de37dbb1db
Showing with 4 additions and 2 deletions.
  1. +4 −2 range.c
View
@@ -914,9 +914,10 @@ range_min(int argc, VALUE *argv, VALUE range)
return range_first(argc, argv, range);
}
else {
struct cmp_opt_data cmp_opt = { 0, 0 };
VALUE b = RANGE_BEG(range);
VALUE e = RANGE_END(range);
int c = rb_cmpint(rb_funcall(b, id_cmp, 1, e), b, e);
int c = OPTIMIZED_CMP(b, e, cmp_opt);
if (c > 0 || (c == 0 && EXCL(range)))
return Qnil;
@@ -951,8 +952,9 @@ range_max(int argc, VALUE *argv, VALUE range)
return rb_call_super(argc, argv);
}
else {
struct cmp_opt_data cmp_opt = { 0, 0 };
VALUE b = RANGE_BEG(range);
int c = rb_cmpint(rb_funcall(b, id_cmp, 1, e), b, e);
int c = OPTIMIZED_CMP(b, e, cmp_opt);
if (c > 0)
return Qnil;

0 comments on commit ab3a40c

Please sign in to comment.