Программирование на языке Ruby - [194]

Шрифт
Интервал

и… получать удовольствие.

Можно использовать >rcov и в качестве библиотеки для написания аналогичных инструментов анализа. Ее API состоит из трех основных классов:

• >Rcov::FileStatistics позволяет отличить исполняемые предложения от комментариев (и тем самым уточнить статистику покрытия);

• >Rcov::CodeCoverageAnalyzer применяется для трассировки выполнения, возвращает информацию о покрытии и счетчики выполненных предложений;

• >Rcov::CallSiteAnalyzer нужен для того, чтобы понять, где определены методы и откуда они вызываются.

Обсуждение API далеко выходит за рамки этого раздела. Почитайте документацию и начинайте экспериментировать.

16.6. Измерение производительности

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

Конечно, быстродействие имеет значение. Иногда даже очень большое. Однако начинать думать об этом на раннем этапе цикла разработки — ошибка. Как говорится, «преждевременная оптимизация — источник всех зол»; эту мысль впервые высказал Хоар (Hoare), а потом подтвердил Кнут (Knuth). Или, перефразируя, сначала пусть работает правильно, а уж потом быстро». На уровне отдельного приложения эта рекомендация обычно оказывается хорошим эвристическим правилом, хотя для больших систем она, быть может, и не так актуальна.

Я бы еще добавил: «Не оптимизируйте, пока не измерите».

Это не такое уж серьезное ограничение. Просто не приступайте к переработке ради скорости, пока не ответите на два вопроса: «Действительно ли программа работает медленно? Какие именно ее части снижают производительность?»

Второй вопрос важнее, чем кажется на первый взгляд. Программисты часто уверены, что и так знают, на что программа тратит большую часть времени, но специальные исследования убедительно свидетельствуют о том, что в среднем эти догадки имеют очень мало общего с действительностью. «Теоретическая» оптимизация для большинства из нас — плохая идея.

Нам нужны объективные измерения. Профилировщик нужен.

В комплект поставки Ruby входит профилировщик >profile. Для его вызова достаточно включить библиотеку:

>ruby -rprofile myprog.rb

Рассмотрим листинг 16.6. Эта программа открывает файл >/usr/share/dict/words и ищет в нем анаграммы. Затем смотрит, у каких слов оказалось больше всего анаграмм, и распечатывает их.

Листинг 16.6. Поиск анаграмм в словаре

>words = File.readlines("/usr/share/dict/words")

>words.map! {|x| x.chomp }


>hash = {}

>words.each do |word|

> key = word.split("").sort.join

> hash[key] ||= []

> hash [key] << word

>end


>sizes = hash.values.map {|v| v.size }

>most = sizes.max

>list = hash.find_all {|k,v| v.size == most }


>puts "Ни у одного слова нет более #{most-1} анаграмм."

>list.each do |key,val|

> anagrams = val.sort

> first = anagrams.shift

> puts "Слово #{first} имеет #{most-1) анаграмм:"

> anagrams.each {|a| puts " #{a}" }

>end


>num = 0

>hash.keys.each do |key|

> n = hash[key].size

> num += n if n > 1

>end


>puts

>puts "Всего слов в словаре: #{words.size},"

>puts "из них имеют анаграммы: #{num}."

Наверняка вам интересно, какие получились результаты. Вот какие:

>Ни у одного слова нет более 14 анаграмм.

>Слово alerts имеет 14 анаграмм:

> alters

> artels

> estral

> laster

> lastre

> rastle

> ratels

> relast

> resalt

> salter

> slater

> staler

> stelar

> talers

>Всего слов в словаре: 483523,

>из них имеют анаграммы: 79537.

На моем компьютере этот файл содержит более 483000 слов, и программа работала чуть меньше 18 секунд. Как вы думаете, на что ушло это время? Попробуем выяснить. Профилировщик выдал более 100 строк, отсортированных в порядке убывания времени. Мы покажем только первые 20:

>%     cumulative self            self    total

>time     seconds seconds  calls  ms/call ms/call  name

>42.78     190.93 190.93      15 12728.67 23647.33 Array#each

>10.78     239.04  48.11 1404333     0.03     0.04 Hash#[]

> 7.04     270.48  31.44       2 15720.00 25575.00 Hash#each

> 5.66     295.73  25.25  483523     0.05     0.05 String#split

> 5.55     320.51  24.78 1311730     0.02     0.02 Array#size

> 3.64     336.76  16.25       1 16250.00 25710.00 Array#map

> 3.24     351.23  14.47  483524     0.03     0.03 Array#sort

> 3.12     365.14  13.91  437243     0.03     0.03 Fixnum#==

> 3.04     378.72  13.58  483526     0.03     0.03 Array#join

> 2.97     391.98  13.26  437244     0.03     0.03 Hash#default

> 2.59     403.53  11.55  437626     0.03     0.03 Hash#[]=

> 2.43     414.38  10.85  483568     0.02     0.02 Array#<<

> 2.29     424.59  10.21       1 10210.00 13430.00 Array#map!

> 1.94     433.23  8.64   437242     0.02     0.02 Fixnum#<=>

> 1.86     441.54  8.31   437244     0.02     0.02 Fixnum#>

> 0.72     444.76  3.22   483524     0.01     0.01 String#chomp

> 0.11     445.26  0.50        4   125.00   125.00 Hash#keys

> 0.11     445.73  0.47        1   470.00   470.00 Hash#values

> 0.06     446.00  0.27        1   270.00   270.00 IO#readlines

> 0.05     446.22  0.22    33257     0.01     0.01 Fixnum#+

Видно, что больше всего времени программа тратит в методе >Array#each. Это понятно: ведь цикл выполняется для каждого слова и на каждой итерации делает довольно много. Среднее значение в данном случае сбивает с толку, поскольку почти все время уходит на первый вызов


Рекомендуем почитать
Графика DirectX в Delphi

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


Вторая жизнь старых компьютеров

Сейчас во многих школах, институтах и других учебных заведениях можно встретить компьютеры старого парка, уже отслужившие свое как морально, так и физически. На таких компьютерах можно изучать разве что Dos, что далеко от реалий сегодняшнего дня. К тому же у большинства, как правило, жесткий диск уже в нерабочем состоянии. Но и выбросить жалко, а новых никто не дает. Различные спонсоры, меценаты, бывает, подарят компьютер (один) и радуются, как дети. Спасибо, конечно, большое, но проблемы, как вы понимаете, этот компьютер в общем не решает, даже наоборот, усугубляет, работать на старых уже как-то не хочется, теперь просто есть с чем сравнивать.


DirectX 8. Начинаем работу с DirectX Graphics

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


Симуляция частичной специализации

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


Обработка событий в С++

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


Питон — модули, пакеты, классы, экземпляры

Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.