我在 String 类的文档中读到 eql?
是一个严格的相等运算符,没有类型转换,而 ==
是一个试图转换的相等运算符其次,它的参数是一个字符串,而且,这个方法的 C 源代码确认:
eql?
源代码:
static VALUE
rb_str_eql(VALUE str1, VALUE str2)
{
if (str1 == str2) return Qtrue;
if (TYPE(str2) != T_STRING) return Qfalse;
return str_eql(str1, str2);
}
==
源代码:
VALUE
rb_str_equal(VALUE str1, VALUE str2)
{
if (str1 == str2) return Qtrue;
if (TYPE(str2) != T_STRING) {
if (!rb_respond_to(str2, rb_intern("to_str"))) {
return Qfalse;
}
return rb_equal(str2, str1);
}
return str_eql(str1, str2);
}
但是当我尝试对这些方法进行基准测试时,令我惊讶的是 ==
比 eql?
快了 20%!
我的基准代码是:
require "benchmark"
RUN_COUNT = 100000000
first_string = "Woooooha"
second_string = "Woooooha"
time = Benchmark.measure do
RUN_COUNT.times do |i|
first_string.eql?(second_string)
end
end
puts time
time = Benchmark.measure do
RUN_COUNT.times do |i|
first_string == second_string
end
end
puts time
和结果:
ruby 1.9.3-p125:
26.420000 0.250000 26.670000 ( 26.820762)
21.520000 0.200000 21.720000 ( 21.843723)
ruby 1.9.2-p290:
25.930000 0.280000 26.210000 ( 26.318998)
19.800000 0.130000 19.930000 ( 19.991929)
那么,当我为两个相似的字符串运行它时,谁能解释为什么更简单的 eql?
方法比 ==
方法慢?
最佳答案
您看到差异的原因不与 ==
与 eql?
的实现有关,但这是由于以下事实Ruby 优化运算符(如 ==
)以避免尽可能进行正常的方法查找。
我们可以通过两种方式验证这一点:
为
==
创建别名并调用它。您会得到与eql?
相似的结果,因此比==
慢。比较使用
send :==
和send :eql?
,你会得到相似的时间;速度差异消失了,因为 Ruby 只会使用优化直接调用运算符,而不是使用send
或__send__
。
这是显示两者的代码:
require 'fruity'
first = "Woooooha"
second = "Woooooha"
class String
alias same_value? ==
end
compare do
with_operator { first == second }
with_same_value { first.same_value? second }
with_eql { first.eql? second }
end
compare do
with_send_op { first.send :==, second }
with_send_eql { first.send :eql?, second }
end
结果:
with_operator is faster than with_same_value by 2x ± 0.1
with_same_value is similar to with_eql
with_send_eql is similar to with_send_op
如果您好奇的话,运算符的优化在 insns.def
中.
注意:此答案仅适用于 Ruby MRI,例如,如果 JRuby/rubinius 中存在速度差异,我会感到惊讶。
关于ruby - 为什么 == 比 eql 快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10257096/