Ruby if语句优化重构最佳实践

时间:2018-07-03 13:11:09

标签: ruby performance optimization refactoring ruby-hash

我在这里遇到了一个非常普遍的重构情况,在浏览了一些博客之后,我仍然对此没有任何满意的评论。所以在这里问一个问题。

h = {
  a: 'a',
  b: 'b'
}
new_hash = {}
new_hash[:a] = h[:a].upcase if h[:a].present?

我的朋友说,可以按照以下方式重构此代码以提高性能。

a = h[:a]
new_hash[:a] = a.upcase if a.present?

乍一看,它看起来有些优化。但这会带来很大的不同还是过分优化?哪种风格应该被首选?

  

正在寻求专家意见:)

使用Benchmark n = 1000

更新
              user     system      total        real
hash lookup  0.000000   0.000000   0.000000 (  0.000014)
new var      0.000000   0.000000   0.000000 (  0.000005)
AND op       0.000000   0.000000   0.000000 (  0.000018)
try          0.000000   0.000000   0.000000 (  0.000046)

使用宝石Memory Benchmark使用benchmark-memory更新

Calculating -------------------------------------
         hash lookup    40.000  memsize (    40.000  retained)
                         1.000  objects (     1.000  retained)
                         1.000  strings (     1.000  retained)
             new var     0.000  memsize (     0.000  retained)
                         0.000  objects (     0.000  retained)
                         0.000  strings (     0.000  retained)
              AND op    40.000  memsize (    40.000  retained)
                         1.000  objects (     1.000  retained)
                         1.000  strings (     1.000  retained)
                 try   200.000  memsize (    40.000  retained)
                         5.000  objects (     1.000  retained)
                         1.000  strings (     1.000  retained)

2 个答案:

答案 0 :(得分:1)

优化的方法各不相同,其中包括内存优化,性能优化以及可读性和代码结构。

性能:由于在O(1)中访问哈希,因此对速度和性能几乎没有任何影响。尝试使用benchmark来看看自己几乎没有区别

You can check this article about hash lookup and why it's so fast

内存:您朋友的代码未如您优化,因为他初始化了另一个对象a,而您初始化了另一个对象。

可读性和样式:乍一看,您朋友的代码看起来像是更少的行,而且更具描述性。但请记住,您可能需要对哈希中的每个键/值都执行此操作,因此您可能需要具有ab,并且随着哈希的进行而继续进行(这样,最好遍历哈希值)。没什么可以在这里看的

答案 1 :(得分:1)

根据您的情况,present?之类的rails方法可能很脏,并且肯定会影响性能。如果您只关注nil检查,而不关注空Array或空白String之类的东西,那么使用纯红宝石方法将“快得多”(引号是为了强调以下事实:在这个基本示例中,性能完全无关紧要)

因为我们正在对事物进行基准测试。

设置

h = {
  a: 'a',
  b: 'b'
}


class Object
  def present? 
    !blank?
  end
  def blank?
    respond_to?(:empty?) ? !!empty? : !self
  end
end

def hash_lookup(h)
  new_hash = {}
  new_hash[:a] = h[:a].upcase if h[:a].present?
  new_hash
end

def new_var(h)
  new_hash = {}
  a = h[:a]
  new_hash[:a] = a.upcase if a.present?
  new_hash
end

def hash_lookup_w_safe_nav(h)
  new_hash = {}
  new_hash[:a] = h[:a]&.upcase
  new_hash
end

def hash_lookup_wo_rails(h)
  new_hash = {}
  new_hash[:a] = h[:a].upcase if h[:a]
  new_hash
end

def new_var_wo_rails(h)
  new_hash = {}
  a = h[:a]
  new_hash[:a] = a.upcase if a
  new_hash
end

基准

N = [1_000,10_000,100_000]
require 'benchmark'
N.each do |n|
  puts "OVER #{n} ITERATIONS"
  Benchmark.bm do |x|
    x.report(:new_var) { n.times {new_var(h)}}
    x.report(:hash_lookup) { n.times {hash_lookup(h)}}
    x.report(:hash_lookup_w_safe_nav) { n.times {hash_lookup_w_safe_nav(h)}}
    x.report(:hash_lookup_wo_rails) { n.times {hash_lookup_wo_rails(h)}}
    x.report(:new_var_wo_rails) { n.times {new_var_wo_rails(h)}}
  end
end

输出

OVER 1000 ITERATIONS
                        user     system      total        real
new_var                 0.001075   0.000159   0.001234 (  0.001231)
hash_lookup             0.002441   0.000000   0.002441 (  0.002505)
hash_lookup_w_safe_nav  0.001077   0.000000   0.001077 (  0.001077)
hash_lookup_wo_rails    0.001100   0.000000   0.001100 (  0.001145)
new_var_wo_rails        0.001015   0.000000   0.001015 (  0.001016)
OVER 10000 ITERATIONS
                        user     system      total        real
new_var                 0.010321   0.000000   0.010321 (  0.010329)
hash_lookup             0.010104   0.000015   0.010119 (  0.010123)
hash_lookup_w_safe_nav  0.007211   0.000000   0.007211 (  0.007213)
hash_lookup_wo_rails    0.007508   0.000000   0.007508 (  0.017302)
new_var_wo_rails        0.008186   0.000026   0.008212 (  0.016679)
OVER 100000 ITERATIONS
                        user     system      total        real
new_var                 0.099400   0.000249   0.099649 (  0.192481)
hash_lookup             0.101419   0.000009   0.101428 (  0.199788)
hash_lookup_w_safe_nav  0.078156   0.000010   0.078166 (  0.140796)
hash_lookup_wo_rails    0.078743   0.000000   0.078743 (  0.166815)
new_var_wo_rails        0.073271   0.000000   0.073271 (  0.125869)