Как стать автором
Обновить
159.7
JUG Ru Group
Конференции для Senior-разработчиков

Практическое руководство по анализу производительности приложений

Время на прочтение 17 мин
Количество просмотров 12K
Вы уже наверняка знаете, что спустя несколько месяцев после конференций мы выкладываем видеозаписи всех докладов. А для самых лучших, как в случае с кейноутом Саши goldshtn Гольдштейна, мы готовим еще и расшифровки — чтобы приобщиться могли и те, кто не любит видеоформат.

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



В основе статьи — выступление Саши на конференции DotNext 2017 Piter. Саша работает техническим директором израильской тренинговой и консалтинговой компании Sela и не понаслышке знает, как проводить анализ производительности. Как его лучше начинать, чем завершать, какие инструменты стоит использовать, а каких избегать, читайте под катом.

Анализ производительности: пошаговый план


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

  1. Получение описания проблемы. Это звучит проще, чем есть на самом деле, потому что часто клиенты очень плохо описывают проблемы.
  2. Построение системной диаграммы. Это дает возможность осознать, из каких частей состоит проблема.
  3. Быстрая проверка производительности. Это позволяет понять, что в системе работает, что – перегружено и т.д.
  4. Понимание того, какой компонент вызывает проблему. На этом этапе мы еще не знаем, в чем проблема, но уже понимаем, где она, так что уже есть прогресс.
  5. Подробный анализ. Этот этап требует больше всего времени.
  6. Поиск корня проблемы.
  7. Устранение проблемы.
  8. Проверка. На этом этапе нужно проверить, устранена ли проблема и работает ли теперь система правильно.
  9. Документирование всего процесса анализа. Это нужно для того, чтобы точно знать, что именно вы сделали, какие инструменты для вас работали, а какие – нет. Это дает возможность не повторять те же ошибки в будущем.

Описание проблемы: почему его иногда бывает так сложно получить?


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



Клиент может обратиться с проблемой вроде:

«Приложение работает слишком МЕДЛЕННО. Пользователи не могут точно сказать, в каких случаях это происходит, но это плохо. Сможете посмотреть?»

Или

«У нас есть бюджет на работы по повышению производительности, в течение двух дней сможете посмотреть на нашу рабочую среду и найти проблему?»

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

«Начиная с 4:25 утра, при обращении к сайту ASP.NET в 95% случаях наблюдается задержка в 1400 мс (обычное время отклика – 60 мс). Задержка наблюдается вне зависимости от географического расположения и не снижается. Мы включили автоматическое масштабирование, но это не помогло».

Такое описание проблемы уже гораздо точнее, потому что я вижу симптомы и понимаю, куда мне смотреть, и я знаю, что можно будет считать решением проблемы (снижение задержки до 60 мс).

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



У каждой компании свои требования к производительности, которые, к сожалению, не всегда формулируются. К примеру, они могут быть такими:

  • 90% всех полнотекстовых запросов должны завершаться не позднее, чем через 200 мс;
  • 99% всех полнотекстовых запросов должны завершаться не позднее, чем через 600 мс;
  • 100% всех полнотекстовых запросов должны завершаться не позднее, чем через 2000 мс.

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

Антипаттерны: как не нужно выполнять анализ


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

  • Делать предположения;
  • Доверять «инстинктам» и абсурдным убеждениям;
  • Искать решение проблемы только там, где его легче всего найти (такое поведение еще называют «эффектом уличного фонаря». Его демонстрировал пьяница из известного анекдота, который искал ключи не там, где он их потерял, а там, где светло);
  • Использовать случайные инструменты;
  • Перекладывать ответственность на инструменты.

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



У меня были инструменты для отслеживания производительности WCF и сервера приложений, у меня был сниффер для сетевого трафика, но у меня не было доступа к системе хранения данных NetApp. После серии тестов я выяснил, что средняя скорость отклика была равна 11 мс, однако в течение 24 часов наблюдались некоторые случаи задержки в 1200 мс. Мне не хватало информации о том, что происходит со стороны NetApp, и необходимо было получить данные тестирования производительности.

От клиента мне удалось получить лишь информацию о том, что скорость отклика системы хранения данных никак не может быть менее 5 мс. На мой вопрос о том, что это за цифра: средняя или пиковая задержка, я получил ответ: это максимальное среднее значение в течение 60 секунд. Я до сих пор не знаю, что это за значение, и я полагаю, что вы тоже не в курсе. Он мог брать среднее значение каждую секунду и затем — максимальное значение от всех средних или, возможно, брал максимальное значение каждую секунду и затем — среднее от максимума…



После этого я нашел в документации для NetApp счетчики производительности, которые считаются допустимыми для этой системы хранения данных. Это средние данные за секунду, а не за минуту. Я попросил у клиента предоставить мне эти данные, однако получил отказ. На этом попытки проведения анализа завершились.

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

Теперь о неудачном использовании инструментов.

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

Запустим средства профилирования Visual Studio в режиме выборки CPU, чтобы проверить производительность поискового робота. Робот может делать некоторые вещи, которые не нагружают процессор, и если мы проведем такой тест, то можем получить примерно такие результаты:



Из этого следует, что необходимо улучшать производительность System.Console.WriteLine, поскольку этот метод замедляет приложение. Однако поисковый робот может просто ждать поступления сетевых данных, это никак не связано с процессором. Поэтому никогда нельзя выбирать инструмент для анализа по принципу «просто потому что мы его купили, и нам нужно отбить его стоимость».

Поиск источника проблемы: метод USE


Иногда вы просто не знаете, что нужно искать, и в этом случае я предлагаю методологию, которая часто используется инженерами во всем мире. Это – метод USE (Utilization, Saturation, Errors), работа с которым происходит в несколько этапов:

  1. На первом необходимо построить диаграмму системы, включая все аппаратные и программные ресурсы и связи между ними;
  2. Затем для каждого ресурса и каждой связи нужно определить три параметра: Utilization – использование (то, насколько загружен ресурс), Saturation – насыщенность (существует ли очередь на использование этого ресурса) и Errors – возникают ли ошибки.
  3. Если с каким-либо параметром связаны проблемы, их необходимо решить.

Вот как может выглядеть метод USE для аппаратных и программных ресурсов:





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

Вот как выглядит чек-лист для систем Windows:

Компонент
Тип
Инструменты анализа или отслеживаемые параметры
Процессор
Загрузка
Processor (_Total)\%ProcessorTime, %User Time Process(My App)\%ProcessorTime
Процессор
Насыщение
System\Processor Queue Length
Процессор
Ошибки
Intel Processor Diagnostic Tool (и другие)
Память
Загрузка
Memory\Available Mbytes
Process\Virtual Size, Private Bytes, Working Set
.NET CLR Memory\#Bytes in all Heaps
VMMap, RAMMap
Память
Насыщение
Memory\Pages/sec
Память
Ошибки
Windows Memory Diagnostic Utility (и другие)
Сеть
Загрузка
Network Interface\Bytes Received/sec, Bytes Sent/sec
Сеть
Насыщение
Network Interface\Output Queue Length, Packets Outbound Discarded, Packets Received Discarded
Сеть
Ошибки
Network Interface\Packets Outbound Errors, Packets Received Errors
Диск
Загрузка
Physical Disc\% Disc Time, % Idle Time, Disc Reds/sec, Disk Writes/sec
Диск
Насыщение
Physical Disc\Current Disk Queue Length
Диск
Ошибки
Chkdisk (и другие инструменты)
Приложение
Ошибки
.NET CLR Exceptions\# of Excepts Thrown/sec
ASP.Net\Error Events Raised

Большинство этих данных можно получить при помощи встроенных счетчиков производительности Windows. Такую проверку можно выполнить очень быстро, но она позволяет сэкономить уйму времени, чтобы затем сосредоточиться на анализе обнаруженных проблем.

Для автоматизации этого процесса можно использовать самые разные решения:

  • Системный монитор Windows (Perfmon) – умеет собирать логи счетчиков производительности постоянно или же только при выполнении каких-либо условий.
  • Typeperf – умеет каждую секунду генерировать файл CSV со значениями счетчиков производительности, которые указаны пользователем.
  • Сторонние решения. Например, если вы работаете с облачным решением, то провайдер, скорее всего, должен предоставлять доступ к инструменту для мониторинга активности процессора, диска, сетевой активности и пр.

Анализ производительности: какие инструменты использовать


Инструменты для анализа производительности можно разделить на три категории:

  • Те, которые помогают определить, как часто это происходит (подсчет). Например, сколько запросов в секунду мы получаем

  • Те, которые помогают определить, сколько времени это занимает (время ожидания). Например, сколько времени занимают мои запросы ASP.NET, сколько времени уходит на переключение между окнами и т.д.

  • Те, которые помогают определить, из-за чего это происходит (стеки). Например, где в исходном коде приложения происходит определенное условие

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

При выборе инструментов важно обращать внимание на пять моментов:

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

Помните об оверхеде!


Любое наблюдение может повлиять на состояние системы, но некоторые инструменты влияют сильнее других. Поэтому перед использованием любого инструмента лучше всего обратиться к документации. Как правило, в ней указывается, чего можно ожидать от применения инструмента (например, повышение нагрузки на процессор на 5-10% при определенных обстоятельствах).



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

Точность: история с безопасными состояниями


Возможно, для тех, кто не работает с Java, это будет новостью, но большинство Java-профайлеров CPU, которые используются разработчиками, выдают неправильные данные (VisualVM, jstack, YourKit, JProfiler…). Они используют GetAllStackTraces, задокументированный JVMTI API. Он выдает семпл того, что делает каждый поток в системе, когда вы вызываете функцию GetAllStackTraces.

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

На скриншоте ниже вы можете увидеть данные научного доклада, посвященного точности Java-профайлеров.



На графике можно увидеть данные четырех профайлеров о том, какой из методов на определенном бенчмарке был самым «горячим». Два из четырех профайлеров (справа и слева) определили, что это был метод jj_scan_token, третий профайлер определил, что это был метод getPositionFromParent, а четвертый – DefaultNameStep.evaluate. То есть четыре профайлера дали совершенно разные показания и совершенно разные методы. И тут дело не в профайлерах, а в API, которые они используют для получения результатов из целевого процесса.

Именно поэтому, если вы используете новый инструмент, нужно обязательно протестировать его в разных условиях (когда процессор активно работает, находится в состоянии покоя или же происходит считывание данных с диска). И вы должны убедиться, что профайлер предоставляет корректные данные, а затем посмотреть на оверхед. Если данные некорректны, то этот профайлер, конечно, не стоит использовать.

Результаты: насколько быстро вы их получите?


Тут я хочу привести пример инструкции по профилированию .NET Core на Linux.



Мы не будем рассматривать ее подробно, обратимся лишь к некоторым моментам. Начинается она с необходимости настройки переменной окружения, с чем у меня, например, возникают проблемы. Ну ладно, допустим, вы это сделали. Инструкция заканчивается тем, что нужно взять ZIP-файл, сгенерированный в результате выполнения всех этих шагов, скопировать на Windows-машину и открыть его с использованием PerfView. И лишь тогда вы сможете проанализировать полученные данные. Звучит нелепо, не правда ли? Выполнить анализ на Linux, а затем открыть его в Windows…

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

$ ./dotnet-mapgen.py generate 4118
$ ./dotnet-mapgen.py merge 4118
# perf record -p 4118 -F 97 -g
# perf script | ./stackcollapse-perf.pl > stacks
$ ./flamegraph.pl stacks > stacks.svg


В итоге вы получаете визуализацию, которая называется флейм-граф. Я остановлюсь на ней подробнее, так как многие Windows и .NET-разработчики с ней еще не знакомы.

Этот метод позволяет визуализировать разные трассировки стека, например, где приложение часто обращается к диску, когда происходит сильная загрузка процессора и т.д. Когда у вас есть множество разных стеков, флейм-граф – это хороший способ наглядно визуализировать их вместо того, чтобы читать много текста. Флейм-граф превращает тысячи страниц трассировки стека в один интерактивный график.

Каждый прямоугольник на графике – это функция. Цвета подбираются в случайном порядке, поэтому их можно игнорировать. Ось Y – это глубина стека, то есть если одна функция вызвала другую, она будет расположена над ней, и на графике будет показана выше. Ось X – это отсортированные стеки (не время). Имея такой график, очень легко приблизить именно ту область, которая вам интересна.



Инвазивность: как не навредить


Инвазивные профайлеры могут плохо влиять на производительность, надежность и отклик системы из-за того, что они слишком «тяжелые». К примеру, при использовании профайлера Visual Studio в instrumentation mode и IntelliTrace происходит перекомпиляция приложения и его запуск с дополнительными маркерами. Такой инструмент невозможно использовать в рабочей среде.

Другой пример – CLR Profiling API, который до сих пор используется в некоторых инструментах. Он основан на внедрении DLL в целевой процесс. Возможно, это приемлемо при разработке, но в рабочей среде внедрять библиотеку в запущенный процесс может быть проблематично.

Экстремальный пример на Linux – это фреймворки трассировки Linux SystemTap, LTTng и SysDig, требующие установки в системе кастомного модуля ядра. Да, вы можете доверять этим ребятам, но все равно это немного подозрительно, что для запуска инструмента для измерения производительности вам необходимо загружать что-то новое в ядро.

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



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



Как вы можете видеть, я собирал информацию об использовании процессора в течение 10 секунд, и в общей сложности получилось 15 МБ данных. Поэтому вряд ли вы сможете тестировать систему с помощью Event Tracing часами – объем данных будет слишком большим. Кроме того, на выполнение CLR Rundown ушло 12,7 секунд, затем еще понадобилось некоторое время на конвертирование и открытие данных (я выделил время красным). То есть, чтобы получить данные, собранные в течение 10 секунд, нужно потратить полминуты на их обработку и открытие.

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

Etrace (https://github.com/goldshtn/etrace) – это open source-интерфейс командной строки для ETW. Вы можете сказать ему, какие события вы хотите увидеть, и он выдаст информацию о них в реальном времени. Как только событие происходит, его можно увидеть в командной строке.


> etrace  --help

Примеры:
etrace --clr GC --event GC/AllocationTick
etrace --kernel Process,Thread,FileIO,FileIOInit  --event File/Create
etrace --file trace.etl --stats
etrace --clr GC --event GC/Start --field PID,TID,Reason[12],Type
etrace --kernel Process --event Process/start --where ImageFileName=myapp
etrace --clr GC --event GC/Start --duration 60
etrace --other Microsoft-Windows-Win32k --event QueuePostMessage
etrace --list CLR,Kernel


К примеру, вы запускаете etrace и говорите: я хочу события GC. Как только запускается такое событие, я хочу видеть его тип, причину, процесс и т.д.



Еще один инструмент, который я написал сам и хочу вам представить, – LiveStacks. Он тоже имеет отношение к ETW. LiveStacks собирает трассировки стека для интересных событий (где находятся сборки мусора, где наблюдается нагрузка на процессор, к каким файлам приложение получает доступ, где оно обращается к диску и т.д.). Главное отличие LiveStacks от других подобных инструментов – вывод информации в реальном времени. Вам не нужно ждать, пока завершится обработка данных, чтобы узнать, какие процессы происходят.

Вот пример режима профилирования процессора, который используется по умолчанию. LiveStacks смотрит на процесс в Visual Studio и показывает стек вызовов в процессе, на который требуется больше всего процессорного времени.



Другой пример: на запрос «покажи мне, где запускается сборка мусора, какой стек вызовов привел к запуску сборки мусора в определенном процессе или во всей системе» LiveStacks в реальном времени выдает стек вызовов с информацией о том, где происходит сборка мусора:



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

> LiveStacks -P JackCompiler -f > stacks.txt
ˆC
>perl flamegraph.pl stacks.txt > stacks.svg


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

Как строить системы для эффективного инструментирования


Когда вы строите систему, библиотеку, архитектуру для своего нового проекта, стоит заранее подумать о некоторых вещах, которые в будущем упростят проведение анализа производительности:

  1. Убедитесь, что стек вызовов для интересных событий (доступ к диску, сборки мусора и т.д.) легко получить;
  2. Внедрите статическое инструментирование кода (tracepoints), чтобы люди могли в реальном времени получить информацию о процессах;
  3. Позаботьтесь о том, чтобы важные процессы можно было включать без оверхеда, без необходимости перезапуска системы, а просто проводя настройку на уровне логов;
  4. Добавьте отладочные точки (probes) для динамического инструментирования;
  5. Составьте примеры и файл документации, чтобы людям, выполняющим анализ производительности, не нужно было тратить лишнее время на понимание того, как работает ваша система.

Пример проекта с очень хорошими средствами инструментирования – .NET на Windows, который используется многими людьми больше 10 лет. Тут есть события ETW, о которых я говорил выше, тут есть возможность захватить стеки вызовов интересных событий и преобразовать их в имена функций. И все это включено по умолчанию!



Сделать проект с такими средствами инструментирования непросто. Скажем, если посмотреть на .NET Core 2.0 для Linux, тут все не так радужно. И вовсе не потому, что в Linux нет хороших инструментов для анализа производительности, а потому что достаточно сложно построить платформу, которую было бы легко профилировать и отлаживать.

Вы хотите знать, что не так с .NET Core 1.0 для Linux? У платформы есть события, однако получить стеки вызовов невозможно, можно только узнать, что событие произошло (что гораздо менее информативно). Еще пример: чтобы преобразовать стеки вызовов для получения имен функций, нужно сделать очень много предварительных действий. Именно поэтому в документации предлагается взять ZIP-файл и открыть его в Windows (я приводил этот пример выше).

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

Будьте осторожны со статистикой!


Статистика и инструменты нас нередко обманывают. Вот о чем всегда нужно помнить в этом отношении:

  1. Усредненные значения бессмысленны.
  2. Медианы бессмысленны.
  3. Перцентили и распределения полезны только в том случае, если вы точно знаете, что делаете.
  4. Используйте хорошую визуализацию для своих данных.
  5. Остерегайтесь феномена coordinated omission.

К примеру, кто-то говорит вам, что «среднее время отклика системы равно 29 мс». Что это может означать? Например, то, что при среднем времени отклика 29 мс самое плохое значение – 50 мс или 60 мс, а самое лучшее – близко к нулю. Или это может означать, что для большинства случаев время отклика составляет 10 мс, но есть режим, в котором система работает гораздо медленнее (со временем отклика до 250 мс), и среднее значение также составляет 29 мс.



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

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



Авторы визуализировали 13 наборов данных с одинаковой сводной статистикой (одно и то же среднее значение x/y, одно стандартное отклонение x/y и одинаковая взаимная корреляция). Однако выглядят эти наборы данных совершенно по-разному. То есть когда вы смотрите только на числа, это не означает ничего. Вы не видите «форму» ваших данных, когда вы смотрите лишь на числа.

BenchmarkDotNet – это библиотека, которую многие из вас используют. Она просто великолепна, но не показывает «форму» ваших данных (по крайней мере, по умолчанию). Когда вы запускаете ее в консоли, она выдает много чисел: средние значения, стандартные отклонения, доверительные интервалы, квартили, однако не «форму» данных. И это очень важно. Для некоторых типов анализа невозможность увидеть «форму» данных означает, что вы пропустите важные вещи.

Вот пример того, что вы можете пропустить, полагаясь на средние значения. На этом графике показано время задержки. В 99% случаев время отклика составляет чуть менее 200 мс, но можно наблюдать периодические заикания – слишком большие задержки (даже до 10 мс), возникающие в течение короткого периода времени.



И в большинстве случаев при выполнении анализа производительности просят обратить внимание именно на заикания – на то, что выше средних значений, на проблемы, с которыми иногда сталкиваются пользователи. Для того чтобы их выявить, необходимо визуализировать все точки данных, как на графике выше, или же построить распределения, как на графике ниже.



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



Представьте, что у вас есть два сервера. Для сервера A в течение 90% времени время задержки составляет 92 мс, для сервера B в течение 90% времени время задержки – 22 мс.



Важно понимать, что вы не можете усреднить эти значения. Это неправда, что на 90% запросов ответ приходит менее чем за 57 мс. На самом деле на 90% запросов ответ приходит быстрее, чем за 68 мс.

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

Иногда можно услышать что-то наподобие: «Кому интересен 99-й перцентиль? Никто из моих пользователей даже не видит этого!» Я поясню, почему это важно, на примере страницы сайта Amazon.com. Она сделала 328 запросов. Если предположить, что все запросы независимы, какова вероятность того, что по крайней мере один из них был в 99-м перцентиле?

P = 1 – 0.99328 ~ 96%

Ответ – 96%. Поэтому очень вероятно, что при переходе на страницу Amazon.com вы получите по крайней мере один запрос в 99-м перцентиле. И если ваши пользователи получают доступ к системе, которая сравнительно сложна, то вероятность того, что с ними произойдет тот самый худший сценарий, очень высока.

Используйте серьезные инструменты для крупных систем!


Последнее, о чем я бы хотел упомянуть в рамках этой статьи, – необходимость использования специальных инструментов для систем, состоящих из большого числа машин. Вот что должны уметь такие инструменты:
  • Собирать данные о производительности с большого числа машин;
  • Ассоциировать действия пользователя с сессией или ID транзакции;
  • Визуализировать данные на информационной панели;
  • Давать возможность фокусироваться на определенном пользователе, запросе, компьютере одним кликом мыши.

Таких инструментов существует очень много. Один из примеров инструментов для мониторинга производительности приложений – Vector от Netflix. На информационной панели вы можете видеть сводную статистику, но в то же время в любой момент можно кликнуть на определенный инстанс и, скажем, просмотреть процессорный флейм-граф для этого инстанса или использование ресурсов диска.



Другой пример – AMP-решение New Relic, которое работает в том числе и с .NET. Оно показывает вам запросы в системе и где вы проводите время, обслуживая эти запросы. И при желании можно переключиться к определенному запросу, к определенной сессии пользователя.

Когда работа завершена: не забывайте документировать!


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

  1. Задокументировать шаги, которые были произведены для поиска, диагностики, решения и проверки проблемы.
  2. Какие инструменты вы использовали? Как их можно улучшить? Что не работало?
  3. Что мешало вам проводить исследование?
  4. Можете ли вы добавить средства мониторинга для системных администраторов?
  5. Можете ли вы добавить инструментарий для тех, кто будет анализировать системы после вас?
  6. Если эта проблема возникнет снова, как можно автоматизировать ее решение?
  7. Документирование процесса поможет вам и всей команде избегать тех же ошибок в будущем, а также, возможно, автоматизировать повторяющиеся задачи.



Саша Гольдштейн — эксперт .NET, гуру производительности и неизменный спикер наших конференций. На двухдневной DotNext, которая пройдет 12-13 ноября в Москве, он выступит с хардкорным докладом Debugging and Profiling .NET Core Apps on Linux. А еще накануне конференции он проведет отдельный тренинг Production Performance and Troubleshooting of .NET Applications.

Из прочих докладов вот эти три вам наверняка также покажутся интересными:

Посмотреть всю программу конференции, виртуально познакомиться со спикерами и приобрести билеты можно на сайте мероприятия.
Теги:
Хабы:
+25
Комментарии 0
Комментарии Комментировать

Публикации

Информация

Сайт
jugru.org
Дата регистрации
Дата основания
Численность
51–100 человек
Местоположение
Россия
Представитель
Алексей Федоров