Программирование на языке 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
и ищет в нем анаграммы. Затем смотрит, у каких слов оказалось больше всего анаграмм, и распечатывает их.
>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
. Это понятно: ведь цикл выполняется для каждого слова и на каждой итерации делает довольно много. Среднее значение в данном случае сбивает с толку, поскольку почти все время уходит на первый вызов
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
Сейчас во многих школах, институтах и других учебных заведениях можно встретить компьютеры старого парка, уже отслужившие свое как морально, так и физически. На таких компьютерах можно изучать разве что Dos, что далеко от реалий сегодняшнего дня. К тому же у большинства, как правило, жесткий диск уже в нерабочем состоянии. Но и выбросить жалко, а новых никто не дает. Различные спонсоры, меценаты, бывает, подарят компьютер (один) и радуются, как дети. Спасибо, конечно, большое, но проблемы, как вы понимаете, этот компьютер в общем не решает, даже наоборот, усугубляет, работать на старых уже как-то не хочется, теперь просто есть с чем сравнивать.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.