my.life.logging.Blog

Словарь инженера по производительности

Инженер по производительности

Выписал из книги “The Well-Grounded Java Developer” перечень метрик, наиболее часто используемых в процессе тюнинга производительности приложения. Представленные здесь метрики – это базовая статистика системы, другие (иногда все же применяемые во время настройки производительности) – менее важны. Думаю, информация будет полезна при чтении статей, посвященных, например, опитимизации производительности JVM.

Latency

Термин “латентность” вполне подойдет здесь в качестве перевода, но если хочется чуть больше прояснить ситуацию, а также отсечь всяческие ассоциации c каким-нибудь “латентным дефицитом железа”, то, возможно, стоит переводить latency как “время отклика” или же “предсказуемость”. Латентность – это длина промежутка времени, который необходим для выполнения одной единицы работы (операции, или транзакции, или еще чего-то подобного) для заданной нагрузки. Довольно часто латентность оценивается только для “нормальной” нагрузки, но в некоторых случаях полезным может оказаться график, показывающий латентность как функцию увеличивающейся нагрузки:

"Локоть" производительности

График показывает внезапную, нелинейную деградацию латентности с возрастанием нагрузки. Это явление называют “локтем производительности”.

Throughput

Если речь идет о компьютерных сетях и о передаче данных, то throughput – это не что иное, как “пропускная способность (канала)”. В случае же компьютерных программ, возможно, лучшим переводом будет “скорость работы” или, если использовать аналогию с физической величиной, “вычислительная мощность”. Вообще throughput – это число единиц работы, которое система может выполнить за определенный период времени с заданным набором ресурсов. Например, для характеристики системы часто используют число транзакций в секунду, выполняемое системой на какой-либо референсной платформе, то есть на сервере конкретного производителя с определенным “железом”, операционной системой и набором программного обеспечения.

Throughput и латентность зависят друг от друга, и, зачастую, увеличить одну из этих характеристик можно только ценой уменьшения другой. Например, использование буферизации, пакетной обработки, асинхронного ввода/вывода (как в Java NIO.2) увеличивает throughput, но за счет латентности. С другой стороны, если сделать код настолько простым, насколько это возможно, и уменьшить количество промежуточной обработки, то это, скорее всего, позволит уменьшить время отклика, но не увеличить throughput. То есть если мы будем посылать каждый байт данных отдельно вместо того, чтобы использовать BufferedOutputStream, то это, очевидно, уменьшит латентность, но throughput при этом серьезно пострадает.

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

Utilization

“Утилизация”, или просто “использование”, представляет собой процент всех доступных ресурсов, который в данный момент задействован для выполнения полезной работы (но не для выполнения служебных задач!), а не находится в режиме ожидания. Если, согласно оценкам, сервер используется на 10 процентов, то это значит, что обычно всего 10 процентов центрального процессора сервера занято выполнением единиц полезной работы. Обратите внимание, что может существовать большая разница между уровнями использования различных ресурсов, таких, например, как центральный процессор и память.

Efficiency

“Эффективность” системы равна throughput, деленному на количество используемых ресурсов. Система, требующая больше ресурсов для достижения того же throughput, менее эффективна. Сравним для примера два кластерных решения. Если для решения A для достижения того же throughput нужно в два раза больше серверов, чем для решения B, тогда решение A эффективно ровно вполовину. Ресурсы можно рассматривать и в терминах их стоимости: если решение X стоит в два раза дороже (или требует в два раза больше обслуживающего персонала), чем решение Y, оно эффективно на 50%.

Capacity

“Обрабатывающая способность”, или же “производительность параллельной обработки”, – это количество единиц работы (транзакций), которые могут происходить в системе в отдельно взятый момент времени. Другими словами, это размер одновременной обработки, доступный в системе при определенных throughput и латентности.

Есть одно интересное свойство обрабатывающей способности: если по мере увеличения нагрузки система достигает максимума своей обрабатывающей способности, а количество единиц работы, которые нужно выполнить одновременно, все увеличивается, то также увеличивается латентность системы в том виде, в котором она видится пользователю системы (потребительская латентность). Для того, чтобы выяснить, будет ли обрабатывающая способность системы соответствовать предполагаемой нагрузке, обычно применяют нагрузочное тестирование.

Scalability

Очевидно, что если добавлять в систему новые ресурсы, throughput и латентность системы будут некоторым образом меняться. Это изменение в throughput или латентности – и есть “масштабируемость” системы. Если для системы A throughput увеличится вдвое после того, как число доступных серверов увеличится в два раза, можно говорить о том, что такая система масштабируется идеально линейным образом. Достичь линейной масштабируемости системы очень тяжело в большинстве обстоятельств.

Масштабируемость системы зависит от многих факторов, и она не постоянна. Система может масштабироваться вполне линейно до определенного момента, а затем начать очень быстро деградировать. Это еще один вид “локтя производительности”.

Degradation

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

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

Comments