为什么==比eql快? [英] Why is == faster than eql?

查看:81
本文介绍了为什么==比eql快?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在String类的文档中读到eql?是严格的等式运算符,没有类型转换,而==是一个等式运算符,它试图将其第二个参数转换为String,然后是C源代码此方法的代码确认:

I read in the documentation for the String class that eql? is a strict equality operator, without type conversion, and == is a equality operator which tries to convert second its argument to a String, and, the C source code for this methods confirms that:

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%! 我的基准代码是:

But when I tried to benchmark these methods, I was suprised that == is faster than eql? by up to 20%! My benchmark code is:

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:

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:

Ruby 1.9.2-p290:

25.930000   0.280000  26.210000 ( 26.318998)
19.800000   0.130000  19.930000 ( 19.991929)

那么,有谁能解释为什么当我为两个相似的字符串运行它时,更简单的eql?方法比==方法要慢的原因?

So, can anyone explain why the more simple eql? method is slower than == method in the case when I run it for two similar strings?

推荐答案

您看到差异的原因与==eql?的实现不相关 ,但这是由于Ruby会优化运算符(例如==),以避免在可能的情况下进行常规方法查找.

The reason you are seeing a difference is not related to the implementation of == vs eql? but is due to the fact that Ruby optimizes operators (like ==) to avoid going through the normal method lookup when possible.

我们可以通过两种方式对此进行验证:

We can verify this in two ways:

  • ==创建别名,然后调用该别名.您将得到与eql?类似的结果,因此结果要比==慢.

  • Create an alias for == and call that instead. You'll get similar results to eql? and thus slower results than ==.

使用send :==send :eql?进行比较,您将获得类似的计时.速度差异消失了,因为Ruby仅将优化用于直接调用运算符,而不使用send__send__.

Compare using send :== and send :eql? instead and you'll get similar timings; the speed difference disappears because Ruby will only use the optimization for direct calls to the operators, not with using send or __send__.

下面的代码同时显示了两者:

Here's code that shows both:

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 .

If you're the curious, the optimizations for operators are in insns.def.

注意:这个答案仅适用于Ruby MRI,例如,如果JRuby/rubinius中存在速度差异,我会感到惊讶.

Note: this answer applies only to Ruby MRI, I would be surprised if there was a speed difference in JRuby / rubinius, for instance.

这篇关于为什么==比eql快?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆