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

Iva*_*ang 2 ruby memory performance ruby-on-rails ruby-on-rails-4

我明白了什么.blank?,.nil?.empty?现在一样.

我在想我为什么不全部更换.nil?,并.empty?.blank?对犯错误少的风险.例如,if current_user.blank?

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

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

提前致谢.

Мал*_*евъ 5

理论

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

  1. :nil?:

    # NilClass
    def nil?
      true
    end
    
    # Object
    def nil?
      false
    end
    
    Run Code Online (Sandbox Code Playgroud)
  2. :empty?:

    # String, Array
    def empty?
      if self.size == 0
        true
      else
        false
      end
    end
    
    Run Code Online (Sandbox Code Playgroud)
  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
    
    Run Code Online (Sandbox Code Playgroud)

正如您可能看到的各种类实现了各种方法风格.在的情况下,String类是需要时间的单一的Regexp,在以下情况下Object,包括HashArray需要时间调用到:respond并返回一个值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 ) }
Run Code Online (Sandbox Code Playgroud)

结果:

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

正如你可以看到,从表的速度的情况下结束显而易见的冠军是方法:blank?String类.对于一个简单empty?的类方法,它的执行时间减少了3-4次.Object的:blank?方法只有1.5倍的执行时间降级.注意,其中的:respond_to方法只有几次执行,因为据我所知,ruby解释器缓存其执行结果.所以,结论.尽量避免使用String的.blank?方法.

另外,如果您需要知道如何使用这些方法,请参见此处.