зеркало из https://github.com/github/ruby.git
Make opt_eq and opt_neq insns leaf
# Benchmark zero? ``` require 'benchmark/ips' Numeric.class_eval do def ruby_zero? self == 0 end end Benchmark.ips do |x| x.report('0.zero?') { 0.ruby_zero? } x.report('1.zero?') { 1.ruby_zero? } x.compare! end ``` ## VM No significant impact for VM. ### before ruby 2.7.0dev (2019-08-04T02:56:02Z master2d8c037e97
) [x86_64-linux] 0.zero?: 21855445.5 i/s 1.zero?: 21770817.3 i/s - same-ish: difference falls within error ### after ruby 2.7.0dev (2019-08-04T11:17:10Z opt-eq-leaf 6404bebd6a) [x86_64-linux] 1.zero?: 21958912.3 i/s 0.zero?: 21881625.9 i/s - same-ish: difference falls within error ## JIT The performance improves about 1.23x. ### before ruby 2.7.0dev (2019-08-04T02:56:02Z master2d8c037e97
) +JIT [x86_64-linux] 0.zero?: 36343111.6 i/s 1.zero?: 36295153.3 i/s - same-ish: difference falls within error ### after ruby 2.7.0dev (2019-08-04T11:17:10Z opt-eq-leaf 6404bebd6a) +JIT [x86_64-linux] 0.zero?: 44740467.2 i/s 1.zero?: 44363616.1 i/s - same-ish: difference falls within error # Benchmark str == str / str != str ``` # frozen_string_literal: true require 'benchmark/ips' Benchmark.ips do |x| x.report('a == a') { 'a' == 'a' } x.report('a == b') { 'a' == 'b' } x.report('a != a') { 'a' != 'a' } x.report('a != b') { 'a' != 'b' } x.compare! end ``` ## VM No significant impact for VM. ### before ruby 2.7.0dev (2019-08-04T02:56:02Z master2d8c037e97
) [x86_64-linux] a == a: 27286219.0 i/s a != a: 24892389.5 i/s - 1.10x slower a == b: 23623635.8 i/s - 1.16x slower a != b: 21800958.0 i/s - 1.25x slower ### after ruby 2.7.0dev (2019-08-04T11:17:10Z opt-eq-leaf 6404bebd6a) [x86_64-linux] a == a: 27224016.2 i/s a != a: 24490109.5 i/s - 1.11x slower a == b: 23391052.4 i/s - 1.16x slower a != b: 21811321.7 i/s - 1.25x slower ## JIT The performance improves on JIT a little. ### before ruby 2.7.0dev (2019-08-04T02:56:02Z master2d8c037e97
) +JIT [x86_64-linux] a == a: 42010674.7 i/s a != a: 38920311.2 i/s - same-ish: difference falls within error a == b: 32574262.2 i/s - 1.29x slower a != b: 32099790.3 i/s - 1.31x slower ### after ruby 2.7.0dev (2019-08-04T11:17:10Z opt-eq-leaf 6404bebd6a) +JIT [x86_64-linux] a == a: 46902738.8 i/s a != a: 43097258.6 i/s - 1.09x slower a == b: 35822018.4 i/s - 1.31x slower a != b: 33377257.8 i/s - 1.41x slower This is needed towards Bug#15589. Closes: https://github.com/ruby/ruby/pull/2318
This commit is contained in:
Родитель
39622232c7
Коммит
346aa557b3
|
@ -1161,7 +1161,7 @@ opt_eq
|
|||
/* This instruction can compare a string with non-string. This
|
||||
* (somewhat) coerces the non-string into a string, via a method
|
||||
* call. */
|
||||
// attr bool leaf = false; /* has rb_str_equal() */
|
||||
// attr bool leaf = true;
|
||||
{
|
||||
val = opt_eq_func(recv, obj, ci, cc);
|
||||
|
||||
|
@ -1177,7 +1177,7 @@ opt_neq
|
|||
(VALUE recv, VALUE obj)
|
||||
(VALUE val)
|
||||
/* Same discussion as opt_eq. */
|
||||
// attr bool leaf = false; /* has rb_str_equal() */
|
||||
// attr bool leaf = true;
|
||||
{
|
||||
val = vm_opt_neq(ci, cc, ci_eq, cc_eq, recv, obj);
|
||||
|
||||
|
|
16
internal.h
16
internal.h
|
@ -2125,6 +2125,22 @@ VALUE rb_str_eql(VALUE str1, VALUE str2);
|
|||
VALUE rb_obj_as_string_result(VALUE str, VALUE obj);
|
||||
const char *ruby_escaped_char(int c);
|
||||
|
||||
/* expect tail call optimization */
|
||||
static inline VALUE
|
||||
rb_str_eql_internal(const VALUE str1, const VALUE str2)
|
||||
{
|
||||
const long len = RSTRING_LEN(str1);
|
||||
const char *ptr1, *ptr2;
|
||||
|
||||
if (len != RSTRING_LEN(str2)) return Qfalse;
|
||||
if (!rb_str_comparable(str1, str2)) return Qfalse;
|
||||
if ((ptr1 = RSTRING_PTR(str1)) == (ptr2 = RSTRING_PTR(str2)))
|
||||
return Qtrue;
|
||||
if (memcmp(ptr1, ptr2, len) == 0)
|
||||
return Qtrue;
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
/* symbol.c */
|
||||
#ifdef RUBY_ENCODING_H
|
||||
VALUE rb_sym_intern(const char *ptr, long len, rb_encoding *enc);
|
||||
|
|
20
string.c
20
string.c
|
@ -3258,22 +3258,6 @@ rb_str_cmp(VALUE str1, VALUE str2)
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* expect tail call optimization */
|
||||
static VALUE
|
||||
str_eql(const VALUE str1, const VALUE str2)
|
||||
{
|
||||
const long len = RSTRING_LEN(str1);
|
||||
const char *ptr1, *ptr2;
|
||||
|
||||
if (len != RSTRING_LEN(str2)) return Qfalse;
|
||||
if (!rb_str_comparable(str1, str2)) return Qfalse;
|
||||
if ((ptr1 = RSTRING_PTR(str1)) == (ptr2 = RSTRING_PTR(str2)))
|
||||
return Qtrue;
|
||||
if (memcmp(ptr1, ptr2, len) == 0)
|
||||
return Qtrue;
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* str == obj -> true or false
|
||||
|
@ -3297,7 +3281,7 @@ rb_str_equal(VALUE str1, VALUE str2)
|
|||
}
|
||||
return rb_equal(str2, str1);
|
||||
}
|
||||
return str_eql(str1, str2);
|
||||
return rb_str_eql_internal(str1, str2);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3312,7 +3296,7 @@ rb_str_eql(VALUE str1, VALUE str2)
|
|||
{
|
||||
if (str1 == str2) return Qtrue;
|
||||
if (!RB_TYPE_P(str2, T_STRING)) return Qfalse;
|
||||
return str_eql(str1, str2);
|
||||
return rb_str_eql_internal(str1, str2);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1506,10 +1506,11 @@ opt_eq_func(VALUE recv, VALUE obj, CALL_INFO ci, CALL_CACHE cc)
|
|||
return rb_float_equal(recv, obj);
|
||||
}
|
||||
}
|
||||
else if (BUILTIN_CLASS_P(recv, rb_cString)) {
|
||||
if (EQ_UNREDEFINED_P(STRING)) {
|
||||
return rb_str_equal(recv, obj);
|
||||
}
|
||||
else if (BUILTIN_CLASS_P(recv, rb_cString) && EQ_UNREDEFINED_P(STRING)) {
|
||||
if (recv == obj) return Qtrue;
|
||||
if (RB_TYPE_P(obj, T_STRING)) {
|
||||
return rb_str_eql_internal(recv, obj);
|
||||
}
|
||||
}
|
||||
|
||||
fallback:
|
||||
|
|
Загрузка…
Ссылка в новой задаче