我应该在性能方面使用`.blank?`吗?

时间:2013-12-28 11:43:41

标签: ruby-on-rails ruby performance memory ruby-on-rails-4

我了解.blank?.nil?.empty?现在做了什么。

我在想为什么我不能将所有.nil?.empty?替换为.blank?,以减少犯错的风险。例如,if current_user.blank?

.blank?方法是否存在性能问题?是更慢还是消耗更多内存

如果是,那有多糟糕?字符串与符号一样糟糕?

提前致谢。

2 个答案:

答案 0 :(得分:5)

理论

这三种方法对各种类都有各种各样的实现:

  1. :nil?

    # NilClass
    def nil?
      true
    end
    
    # Object
    def nil?
      false
    end
    
  2. :empty?

    # String, Array
    def empty?
      if self.size == 0
        true
      else
        false
      end
    end
    
  3. :blank?

    # FalseClass, NilClass
    def blank?
      true
    end
    
    # Object
    def blank?
      respond_to?(:empty?) ? empty? : !self
    end
    
    # TrueClass
    def blank?
      false
    end
    
    # String
    def blank?
      self !~ /[^[:space:]]/
    end
    
  4. 正如您可能看到的各种类实现了各种方法风格。如果是String类,则需要一个Regexp的时间,如果是Object,包括HashArray,则需要花费一些时间来调用:respond {1}}并返回值nil或不返回Object。秒只是花费时间类似于:nil?的操作。 :respond?方法检查:empty?方法的存在,理论上略微超过两次 到:empty?

    调查

    我编写了简单的脚本来模拟这些方法的行为,并计算它们的执行时间:

    #! /usr/bin/env ruby
    
    require 'benchmark'
    
    obj = Object.new
    array = []
    empty_string = ''
    non_empty_string = '   '
    
    funcs = 
    [ proc { empty_string.empty? }, 
      proc { non_empty_string.empty? },
      proc { obj.nil? },
      proc { nil.nil? },
      proc { true },
      proc { respond_to?(:empty?) ? empty? : !self },
      proc { array.respond_to?(:empty?) ? array.empty? : !array },
      proc { non_empty_string !~ /[^[:space:]]/ } ]
    
    def ctime func
       time = 0
       1000.times { time += Benchmark.measure { 1000.times { func.call } }.to_a[5].to_f }
       rtime = time /= 1000000
    end
    
    funcs.each {| func | p ctime( func ) }
    

    结果:

    # empty String :empty?
    # 4.604020118713379e-07
    # non_empty String :empty?
    # 4.5903921127319333e-07
    # Object :nil?
    # 5.041143894195557e-07
    # NilClass :nil?
    # 4.7951340675354e-07
    # FalseClass, NilClass, TrueClass :blank?
    # 4.09862756729126e-07
    # main :blank? ( respond_to returns false )
    # 6.444177627563477e-07
    # Array :blank? ( respond_to returns true )
    # 6.491720676422119e-07
    # String :blank?
    # 1.4315705299377442e-06
    

    正如您所看到的,在速度的情况下,表格末尾的明显冠军是:blank?类的方法String。对于类的简单empty?方法,它的执行时间减少了3-4次。对象的:blank?方法只有1.5倍的执行时间降级。请注意,其中的:respond_to方法只有几次执行,因为据我所知, ruby​​ 解释器会缓存其执行结果。所以,结论。尽量避免使用String的.blank?方法。

    另外,如果您需要知道如何使用这些方法,请参阅here

答案 1 :(得分:3)

在此处查看来源blank?

def blank?
  respond_to?(:empty?) ? empty? : !self
end

技术上它是empty?

的2倍

.blank是否存在性能问题? ?是慢还是消耗更多内存?

嗯,这取决于很多因素

  • 您的应用处理的数据量
  • 服务器硬件
  • 没有收到的请求

但坦率地说,除非你运行推特,否则这不会打扰你