为什么==比eql更快?

sha*_*_ru 17 ruby string benchmarking equality

我在文档中读取了String类,它eql?是一个严格的相等运算符,没有类型转换,并且==是一个等于运算符,它尝试将其参数的第二个转换为String,并且此方法的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);
}
Run Code Online (Sandbox Code Playgroud)

==源代码如下:

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);
}
Run Code Online (Sandbox Code Playgroud)

但是当我尝试对这些方法进行基准测试时,我感到惊讶的==是,速度比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
Run Code Online (Sandbox Code Playgroud)

结果:

Ruby 1.9.3-p125:

26.420000   0.250000  26.670000 ( 26.820762)
21.520000   0.200000  21.720000 ( 21.843723)
Run Code Online (Sandbox Code Playgroud)

Ruby 1.9.2-p290:

25.930000   0.280000  26.210000 ( 26.318998)
19.800000   0.130000  19.930000 ( 19.991929)
Run Code Online (Sandbox Code Playgroud)

那么,任何人都可以解释为什么在我为两个相似的字符串运行它时,更简单的eql?方法比==方法更慢?

pet*_*ter 2

equal? is reference equality
== is value equality
eql? is value and type equality
Run Code Online (Sandbox Code Playgroud)

第三种方法eql?通常用于测试两个对象是否具有相同的值和相同的类型。例如:

puts "integer == to float: #{25 == 25.0}"
puts "integer eql? to float: #{25.eql? 25.0}"

gives:

Does integer == to float: true
Does integer eql? to float: false
Run Code Online (Sandbox Code Playgroud)

所以我想,既然eql?做了更多的检查,它就会变慢,对于字符串来说,至少在我的 Ruby 1.93 上是这样。所以我认为它必须依赖于类型并做了一些测试。比较整数和浮点数时eql?速度要快一些。当比较整数时==要快得多,直到x2。理论错误,回到起点。

下一个理论:比较相同类型的两个值会更快,其中一个被证明是正确的,在它们属于相同类型的情况下==总是更快,eql?当类型不同时更快,直到x2。

没有时间比较所有类型,但我确信您会得到不同的结果,尽管相同类型的比较总是给出相似的结果。有人能证明我错了吗?

以下是我的 OP 测试结果:

 16.863000   0.000000  16.863000 ( 16.903000) 2 strings with eql?
 14.212000   0.000000  14.212000 ( 14.334600) 2 strings with ==
 13.213000   0.000000  13.213000 ( 13.245600) integer and floating with eql?
 14.103000   0.000000  14.103000 ( 14.200400) integer and floating with ==
 13.229000   0.000000  13.229000 ( 13.410800) 2 same integers with eql?
  9.406000   0.000000   9.406000 (  9.410000) 2 same integers with ==
 19.625000   0.000000  19.625000 ( 19.720800) 2 different integers with eql?
  9.407000   0.000000   9.407000 (  9.405800) 2 different integers with ==
 21.825000   0.000000  21.825000 ( 21.910200) integer with string with eql?
 43.836000   0.031000  43.867000 ( 44.074200) integer with string with ==
Run Code Online (Sandbox Code Playgroud)