Измерение производительности
Модуль Benchmark
«Измерение производительности» — бесплатный урок Ruby Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Ruby Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Ruby Academy содержит 4 уроков всего.
Зачем измерять?
Оптимизация без измерений — это гадание. Модуль Benchmark из стандартной библиотеки Ruby точно измеряет время выполнения кода.
- Находите медленные участки до их изменения
- Объективно сравнивайте реализации
- Избегайте преждевременной оптимизации
require 'benchmark'
time = Benchmark.realtime do
1_000_000.times { |i| i * 2 }
end
puts "Took #{time.round(4)}s"Benchmark.measure
Benchmark.measure возвращает отчёт о пользовательском, системном и реальном времени.
- Пользовательское время — это время CPU, затраченное вашим кодом
- Реальное время — это прошедшее время по часам
require 'benchmark'
result = Benchmark.measure do
500_000.times { |i| i.to_s }
end
puts resultBenchmark.bm
Benchmark.bm запускает несколько блоков и помечает их в таблице.
- Передайте ширину метки для выравнивания
- Каждый вызов
x.reportзанимает одну строку
require 'benchmark'
Benchmark.bm(10) do |x|
x.report('to_s:') { 100_000.times { |i| i.to_s } }
x.report('inspect:') { 100_000.times { |i| i.inspect } }
endBenchmark.bmbm
Benchmark.bmbm сначала выполняет пробный прогон, чтобы прогреть кэши и сборщик мусора и получить более достоверные результаты.
- Первый проход отбрасывается
- Второй проход является настоящим измерением
require 'benchmark'
Benchmark.bmbm do |x|
x.report('sum:') { (1..100_000).sum }
x.report('reduce:') { (1..100_000).reduce(:+) }
endБыстрое измерение времени с realtime
Benchmark.realtime возвращает только секунды, прошедшие по часам, в виде числа с плавающей точкой.
- Это самый простой способ измерить время одного блока
- Подходит для разовых проверок
require 'benchmark'
elapsed = Benchmark.realtime do
arr = Array.new(100_000) { rand }
arr.sort
end
puts "Sorted in #{elapsed.round(4)}s"Монотонные часы
Для точного измерения времени, не зависящего от изменений системных часов, используйте Process.clock_gettime с монотонными часами.
- Не зависит от корректировок NTP
- Самый точный встроенный вариант
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
200_000.times { |i| i * i }
finish = Process.clock_gettime(Process::CLOCK_MONOTONIC)
puts "Elapsed: #{(finish - start).round(4)}s"Сравнение двух подходов
Тесты производительности особенно полезны при сравнении вариантов. Запускайте оба варианта при одинаковой нагрузке.
- Размер входных данных должен быть достаточно большим для измерения
- Повторяйте измерения, чтобы уменьшить шум
require 'benchmark'
arr = (1..100_000).to_a
Benchmark.bm(8) do |x|
x.report('map:') { arr.map { |n| n * 2 } }
x.report('each:') { r = []; arr.each { |n| r << n * 2 } }
endОстерегайтесь микроизмерений
Крошечные тесты производительности могут вводить в заблуждение.
- JIT и кэши могут не отражать реальные рабочие нагрузки
- Сборщик мусора может сработать во время измерения
- Измеряйте реалистичные объёмы данных
require 'benchmark'
# Too small to be meaningful
t = Benchmark.realtime { 10.times { |i| i + 1 } }
puts "Misleadingly tiny: #{t}s"Итераций в секунду
Часто вас интересует пропускная способность — количество операций в секунду. Пакет benchmark-ips сообщает это значение, но его можно приблизительно вычислить вручную.
- Подсчитайте итерации за фиксированный промежуток времени
- Большее значение ips означает более высокую скорость
deadline = Process.clock_gettime(Process::CLOCK_MONOTONIC) + 0.2
count = 0
while Process.clock_gettime(Process::CLOCK_MONOTONIC) < deadline
count += 1
'hello'.upcase
end
puts "Iterations in 0.2s: #{count}"Управление сборщиком мусора
Сборщик мусора может исказить результаты. Вы можете временно отключить его, чтобы получить более стабильные значения.
- Вызовите
GC.disableперед измерением, аGC.enable— после - Используйте это осторожно, чтобы избежать роста потребления памяти
require 'benchmark'
GC.disable
t = Benchmark.realtime { 100_000.times { |i| i.to_s } }
GC.enable
puts "Without GC: #{t.round(4)}s"Усреднение нескольких запусков
Запустите тест несколько раз и усредните результаты, чтобы сгладить разброс.
- При необходимости отбросьте самый медленный выброс
- Для стабильности сообщайте медиану
require 'benchmark'
times = 3.times.map do
Benchmark.realtime { (1..50_000).map { |n| n * n } }
end
avg = times.sum / times.size
puts "Average: #{avg.round(4)}s"Проверка
Проверьте свои знания о тестировании производительности.
Повторение
Вы научились измерять производительность:
- Модуль
Benchmarkточно измеряет время выполнения кода realtime,measure,bmиbmbmпредназначены для разных задач- Для точного измерения времени используйте монотонные часы
- Избегайте вводящих в заблуждение микроизмерений и учитывайте работу сборщика мусора
- Усредняйте несколько запусков, чтобы уменьшить шум
Далее вы воспользуетесь специализированными инструментами профилирования.
Часто задаваемые вопросы
Урок «Измерение производительности» бесплатный?
Да — полный текст урока «Измерение производительности» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Ruby Academy, подпишись на CoddyKit PRO. Курс Ruby Academy содержит 4 уроков всего.
Чему я научусь в уроке «Измерение производительности»?
Модуль Benchmark Ты практикуешь Ruby Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Ruby Academy?
Предыдущий опыт не требуется. Ruby Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.
Сколько времени занимает урок «Измерение производительности»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Ruby Academy?
Да. Каждый урок Ruby Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Измерение производительности
- Инструменты профилирования
- Оптимизация памяти
- Распространённые узкие места