• время, затраченное процессором в режиме пользователя (в секундах);
• время, затраченное процессором в режиме ядра (в секундах);
• полное затраченное время — сумму вышеупомянутых величин;
• время работы программы (по часам).
Для сравнения производительности отдельных участков удобен метод Benchmark.bm
. Передайте ему блок, а он сам передаст блоку объект формирования отчета. Если вызвать этот объект, передав ему метку и блок, то он выведет метку, а за ней временные характеристики блока. Пример:
require 'benchmark'
n = 200_000
s1 = ""
s2 = ""
s3 = ""
Benchmark.bm do |rep|
rep.report("str << ") { n.times { s1 << "x" } }
rep.report("str.insert ") { n.times { s3.insert(-1,"x") } }
rep.report("str += ") { n.times { s2 += "x" } }
end
Здесь мы сравниваем три способа добавить символ в конец строки, дающие один и тот же результат. Чтобы можно было получить более точные цифры, каждая операция выполняется 200000 раз. Вот что вышло:
user system total real
str << 0.180000 0.000000 0.180000 ( 0.174697)
str.insert 0.200000 0.000000 0.200000 ( 0.200479)
str += 15.250000 13.120000 28.370000 (28.375998)
Обратите внимание, что последний вариант на два порядка медленнее остальных. Почему? Какой урок можно извлечь отсюда?
Вы можете предположить, что оператор +
почему-то работает медленно, но дело в другом. Это единственный из трех способов, который не работает с одним и тем же объектом, а каждый раз создает новый.
Стало быть, вывод такой: создание объекта — дорогая операция. Библиотека Benchmark может преподать много подобных уроков, но я все же рекомендую сначала заняться высокоуровневым профилированием.
Метод inspect
(и вызывающий его метод p
) предназначен для вывода объектов в виде, понятном человеку. В этом смысле он является связующим звеном между тестированием и отладкой, поэтому рассмотрение его в этой главе оправданно.
Проблема в том, что результат, формируемый методом p
, бывает трудно читать. Из-за этого и появилась библиотека pp
, добавляющая одноименный метод. Рассмотрим следующий искусственный пример объекта my_obj
:
class MyClass
attr_accessor :alpha, :beta, :gamma
def initialize(a,b,c)
@alpha, @beta, @gamma = a, b, с
end
end
x = MyClass.new(2, 3, 4)
y = MyClass.new(5, 6, 7)
z = MyClass.new(7, 8, 9)
my_obj = { x => y, z => [:p, :q] }
p my_obj
Вызов метода p
печатает следующее:
{#
@gamma=4>=>#,
#=>[:p, :q]}
Все правильно и в общем-то даже читаемо. Но… некрасиво. А давайте затребуем библиотеку pp
и воспользуемся предоставляемым ей методом pp
:
require 'pp'
# ...
pp my_obj
Теперь вывод приобретает такой вид:
{#=>[:p, :q],
#=>
#}
Мы получили хотя бы пробелы и разбиение на строки. Уже лучше. Но можно пойти еще дальше. Предположим, что в классе MyClass
определен специальный метод pretty_print
:
class MyClass
def pretty_print(printer)
printer.text "MyClass(#@alpha, #@beta, #@gamma)"
end
end
Аргумент printer передается вызывающей программой (или методом pp). Это аккумулятор текста, являющийся экземпляром класса PP
; мы вызываем его метод text
и передаем ему текстовое представление self
. Вот что получается в результате:
{MyClass(7, 8, 9)=>[:p, :q] , MyClass(2, 3, 4)=>MyClass(5, 6, 7)}
Разумеется, можно настроить поведение по своему вкусу. Можно, например, печатать переменные экземпляра на разных строчках с отступами.
На самом деле в библиотеке pp
есть много средств для подготовки ваших классов к совместной работе с методом pp
. Методы object_group
, seplist
, breakable
и прочие позволяют управлять расстановкой запятых, разбиением на строки и другими способами форматирования. Дополнительную информацию можно найти в документации на сайте http://ruby-doc.org.
В этой главе мы рассмотрели некоторые подходы к тестированию (преимущественно, к автономному тестированию компонентов). Мы познакомились с библиотекой Test::Unit
и комплектом инструментов ZenTest.
Мы бросили беглый взгляд на отладчик Ruby, а также показали, как с помощью библиотеки ruby-breakpoint
можно переходить в интерактивную оболочку irb
для проведения сеанса отладки.
Мы рассмотрели инструмент для анализа покрытия кода rcov
и обсудили, для чего могут понадобиться такие измерения. Наконец, остановились на профилировании и замере временных характеристик программы на Ruby.
Читать дальше
Конец ознакомительного отрывка
Купить книгу