Skip to content

Latest commit

 

History

History
134 lines (80 loc) · 15.5 KB

speech.md

File metadata and controls

134 lines (80 loc) · 15.5 KB

--

Программа должна работать (Ну как же без этого!) И еще она должна работать быстро.

Производительность программного обеспечения (ПО) является важным аспектом в разработке любого программного продукта. Актуальность вопроса объясняется постоянно возрастающей сложностью и значимостью программных средств (под значимостью я понимаю рост количества пользователей ПО).

Как нельзя ожидать, что программа будет работать без ошибок с самого первого запуска, так нельзя ожидать того, что программа просто так начнет показывать высокую производительность. В соответствии с принципом Парето, только 20% программного кода будет оказывать существенное влияние на производительность приложения в целом. Эти 20% процентов зачастую называются bottleneck, бутылочным горлышком, или же просто узким местом.

--

Для того, чтобы выявить узкое место в приложении нужны две вещи:

  1. Требования к производительности. Причем требования должны быть составлены еще на этапе проектирования программного обеспечения.
  2. Сведения о работе приложения, иначе такие сведения называют значениями характеристик производительности. Такие значения можно получать из различных источников. Можно анализировать отчеты счетчиков производительности. Можно запускать профилировщики и искать проблемы. А можно просто собирать информацию о работе приложения под нагрузкой.

--

Требования должны быть сформулированы на этапе проектирования приложения и уточнены далее на этапе разработки и поддержки. Требования к производительности во многом зависят от назначения приложения и его архитектуры. Было бы глупо требовать от приложений таких как Web-база объема используемой оперативной памяти сравнимых с объемом, требуемых для мобильных приложений.

Рассмотрим примеры плохо сформулированных требований:

  • Высокая отзывчивость при одновременном доступе нескольких пользователей.
  • Низкий объем потребления памяти при небольшом количестве посетителей.

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

Веб-сервер Время на обработку запроса не более 300 мс Одновременно не более 300 запросов в секунду
Веб-сервер Объем используемой оперативной памяти не более 20 Гб Одновременно открыто не более 5000 сеансов пользователей
Клиентское ПО Время открытия приложения не должно превышать 1500 мс 8 Гб оперативной памяти
Клиентское ПО Нагрузка на ЦП в режиме простоя не должна превышать 1% Процессор Intel Core i7 4790 3,6 ГГц или AMD FX-9590 4,7 ГГц

--

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

                 |       

---------------------|-------------------------------------------------- Нагрузка на CPU | % Использование памяти | Килобайты, мегабайты, гигабайты Время выполнения | Миллисекунды Сборка мусора | Продолжительность % от общего времени выполнения Попадания в кэш | Количество попаданий в секунду

Это весьма общие характеристики, и они характерны большинству приложений, будь то веб сервер или почтовый клиент.

--

Где же найти место вопросам производительности в процессе разработки ПО?

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

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

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

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

--

Построение догадок и преждевременных выводов об узких местах в приложении - это самое худшее, что может сделать разработчик.

Однажды, когда я активно вел разработку над мобильным android приложением вместе с Димой Николенко, появилась проблема со стандартными библиотечными методами работы с http запросами. Если не ошибаюсь класс называется UrlConnection. У него какая-то жесть была с поддержкой многопоточных запросов на сервер. Решили найти альтернативу, на глаза попался Apache HttpClient с его ThreadSafeClientConnManager, ну я значит решил все, если есть сочетание Thread Safe значит все в порядке. А что оказалось в итоге, этот ThreadSafeClientConnManager плодил кучу ненужных потоков для каждого соединения из-за чего соответственно приложение тормозить стало.

В конце концов, нашли мы нормальную замену всему этому добру OkHttp называется, от команды Square. На этот раз проверили его работу профилировщиком, поставляемым Android Studio и благополучно пошли спать.

--

Вообще все что перечислено выше является разновидностями подходов к профилированию. Само слово профилирование означает одну из форм динамического анализа кода, которая измеряет какие-либо характеристики системы.

--

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

Правда есть ограничение, частота обновления информации у Performance Monitor не поднимается выше чем 1 раз/сек. Поэтому для замеров с частотой тысячи раз в секунду данный инструмент не подойдет.

--

Существует огромное множество различный профилировщиков. Профилирование времени является пожалуй одним из самых распространенных методов выявления узких мест в приложении. Особенно веб. Сегодня я хочу поговорить о двух представителях категории профилировщиков времени.

Первый (MiniProfiler) - это маленькая библиотека главной задачей которой является собрать как можно больше информации о времени выполнении каждого запроса в общем и sql в частности. Данная библиотека была написана командой StackExchange, а эти парни знают толк в производительности, я думаю, что большинство программистов так или иначе пользуются проектами StackExchange (если кто не знает StackOwerflow это один из их проектов).

--

MiniProfiler

Как вы думаете что в этом профиле не так? =) Рассказать об SQL N+1 проблеме

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

--

dotTrace

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

--

dotMemory

Уте́чка па́мяти (англ. memory leak) — процесс неконтролируемого уменьшения объёма свободной оперативной или виртуальной памяти компьютера, связанный с ошибками в работающих программах, вовремя не освобождающих ненужные уже участки памяти, или с ошибками системных служб контроля памяти.

Трафик памяти (англ. memory traffic) - количество памяти выделяемое в единицу времени.

--

Microbenchmarking

Некоторые проблемы не могут быть решены с использованием стандартных методов профилирования. Например, необходимо объяснить свой выбор в использовании той или иной структуры данных. Так как профилировщики вносят свои, и причем достаточно весомые накладные расходы в работу приложения во время профилирования, то приходится производить замеры вручную. Это и называется микрохронометраж.

Но ручной хронометраж таит все в себе кучу подводных камней и необходимо постоянно учитывать внешние факторы, чтобы результат измерения был точным:

  • Тестирование должно выполняться в среде, близкой по своим характеристикам окружению, в котором должно работать разрабатываемое приложение.
  • Тестовые исходные данные по своей структуре должны быть близки фактическим данным.
  • Время выполнения кода поддержки, используемого для настройки окружения, должно быть ничтожно мало, по сравнению со временем выполнения тестируемого кода.
  • Тестируемый код должен выполняться достаточно долго, чтобы ослабить влияние случайных программных и аппаратных флуктуаций.
  • Нужно учитывать различные оптимизации компилятора языка + JIT компилятора

Поэтому самому построить окружение для микрохронометража весьма сложно. И есть вариант - это использовать готовую библиотеку BenchmarkDotNet. О большей части проблем она уже позаботилась и нам по большей части остается, только провести тесты в приближенных условиях.

--

BenchmarkDotNet

Давайте попробуем выяснить что будет быстрее: обойти массив или двусвязный список.

--

Нагрузочное тестирование