Оптимизация одного скрипта

January 26, 2017

Руби дарит нам радость, а взамен жрет память и CPU. Руководствуясь этим тезисом, оптимизирую руби код очень редко. Однако недавно столкнулся в любопытной штукой, когда изменение в одной строчки уменьшило время выполнения c 10 секунд до долей секунды.

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

... if string =~ /#{name}-\d{4}-\d{2}-\d{2}__\d{2}_\d{2}_\d{2}/

Оказалось что создавать регексп на лету - весьма и весьма медленно, лучше создать его один раз и использовать столько раз, сколько надо:

RE = /#{name}-\d{4}-\d{2}-\d{2}__\d{2}_\d{2}_\d{2}/
# ...
... if string =~ RE

Простой бенчмарк показывает, что разница по времени исполнения почти в два порядка, причем в важном для комфорта диапазоне:

require 'benchmark'

c = 60_000
name = "head"
re = /#{name}-tail-\d{4}-\d{2}/
string = "head-tail-2012-12"
i = 0

Benchmark.bm do |bm|
  bm.report { c.times { i += 1 if string =~ /#{name}-tail-\d{4}-\d{2}/ } }
  bm.report { c.times { i += 1 if string =~ /#{name}-tail-\d{4}/ } }
  bm.report { c.times { i += 1 if string =~ /#{name}-tail/ } }
  bm.report { c.times { i += 1 if string =~ re } }
end
puts "i: #{i}"

#  user     system      total        real
# 1.340000   0.020000   1.360000 (  1.373314)
# 0.820000   0.010000   0.830000 (  0.843216)
# 0.390000   0.020000   0.410000 (  0.406644)
# 0.020000   0.000000   0.020000 (  0.035978)
# i: 240000

Так что обычно на руби можно писать как угодно, но иногда нельзя.

comments powered by Disqus