Это краткое пошаговое руководство для тех случаев, когда вам нужно провести тестирование производительности на лету.

Ruby имеет встроенный модуль бенчмаркинга, который прост в использовании и достаточно эффективен, чтобы охватить ваши стандартные варианты использования. Используя одну из нескольких функций, мы можем быстро изолировать неэффективные участки нашего кода.

Сравнительная отчетность

Метод Benchmark.bm дает распечатку показателей производительности для любых блоков кода, которые мы передаем в него. Мы можем разделить это на несколько кусков кода для выполнения, чтобы тестировать разные вещи одновременно. Мы получим несколько отчетов, по одному для каждого использования метода report.

Benchmark.bm do |bench|
  bench.report('Performance Test 1') do
    # execute some code here
  end
  bench.report('Performance Test 2') do
    # execute some other code here
  end
end

В этом уроке мы будем тестировать только один блок кода:

Benchmark.bm do |bench|
  bench.report('Testing some code') do
    # execute some code here
  end
end

Это даст нам вывод, подобный следующему:

user       system     total       real
0.544000   0.036000   0.580000    (1.049005)

В каждом отчете отображается время ЦП пользователя, время ЦП системы, суммарное время ЦП и прошедшее реальное время.

Единицей времени являются секунды.

Таким образом, наш код выполнялся примерно за 1,05 секунды.

Давайте сделаем еще один шаг и профилируем наш код более тщательно.

Профилирование кода

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

Benchmark.bm do |bench|
  bench.report('Testing some code') do
    process_100_records
  end
end

Давайте запустим этот тест 5 раз и запишем результаты.

       user       system     total       real
Run 1: 0.544000   0.036000   0.580000    (1.049005)
Run 2: 0.500000   0.080000   0.580000    (1.059239)
Run 3: 0.520000   0.048000   0.568000    (1.026662)
Run 4: 0.536000   0.048000   0.584000    (1.066434)
Run 5: 0.496000   0.080000   0.576000    (1.050087)

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

Для этого урока мы сохраним все 5 результатов.

Вот краткий сценарий, чтобы определить, какой будет наша ожидаемая среда выполнения с большим пулом данных. Для этого примера у нас есть размер выборки 100 записей и полный размер данных 1 миллион записей.

# This code can be run in a terminal - just edit the variables
def avg(array)
  array.sum(0.0) / array.size
end

def seconds_to_hms(sec)
  "%02d:%02d:%02d" % [sec / 3600, sec / 60 % 60, sec % 60]
end

# Fill in these variables with your own results
realtimes = [1.049005, 1.059239, 1.026662, 1.066434, 1.050087]
sample_size = 100
full_data_size = 1000000
average_time = avg(realtimes)
# predicted runtime for full data size
expected_runtime = average_time / sample_size * full_data_size

p seconds_to_hms expected_runtime

=> "02:55:02"

Этот код будет выполняться около 3 часов(!)

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

Надеюсь, это поможет. Удачи на поле!