Лучшая практика по оптимизации рефактора операторов - PullRequest
0 голосов
/ 03 июля 2018

У меня очень распространенная ситуация с рефакторингом, и после просмотра нескольких блогов я так и не получил удовлетворительного комментария по этому поводу; поэтому задаю вопрос здесь.

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 голосов
/ 03 июля 2018

В зависимости от ваших обстоятельств методы рельсов, такие как present?, могут быть грязными и определенно влиять на производительность. Если вас беспокоит только проверка nil, а не пустые Array или пустые String, то использование чистых методов ruby ​​будет «намного» быстрее (в кавычках подчеркивается тот факт, что производительность в этом случае совершенно несущественна). базовый пример)

Так как мы сравниваем вещи.

Настройка

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)
0 голосов
/ 03 июля 2018

Оптимизация носит разный характер, есть оптимизация памяти, оптимизация производительности, читаемость и структура кода.

Производительность : Практически не влияет на скорость и производительность, потому что к хэшу обращаются в O (1). Попробуйте с помощью benchmark убедиться, что разницы почти нет

Вы можете проверить эту статью о поиске хеша и почему он так быстр

Память : код вашего друга менее оптимизирован, чем ваш, потому что он инициализировал другой объект a, а ваш - нет.

Удобочитаемость и стиль : на первый взгляд код вашего друга выглядит меньше строк и более наглядно. Но имейте в виду, что вам может потребоваться сделать это для каждого ключа / значения в хэше, поэтому вам может потребоваться иметь a, b, и он будет продолжаться, как продолжается ваш хэш (когда это происходит так, это лучше перебрать хеш конечно). Не слишком много, чтобы смотреть здесь TBH

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...