Development

Взаимодействие между процессами влияет на время отклика

(В оригинале – Inter-Process Communication Affects Application Response Time)

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

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

Характерный пример – ripple loading в приложениях, строящих граф отношений между объектами. Ripple loading – это последовательное выполнение большого количества запросов к базе данных для выборки данных, необходимых для построения такого графа (см. Lazy Load в книге «Паттерны архитектуры корпоративных приложений» Мартина Фаулера). Если клиент базы данных – это сервер приложений промежуточного уровня, строящий веб-страницу, то запросы к базе данных выполняются последовательно в одном потоке. Их задержки суммируются, повышая общее время отклика. Даже если один запрос к базе данных занимает всего лишь 10 миллисекунд, для страницы, требующей 10 тысяч запросов (что не так уж и редко), задержка отклика составит уже 10 секунд. Другие примеры включают HTTP-запросы от веб-браузера, вызов распределенного объекта, сообщения типа «запрос-ответ» и другие подобные взаимодействия. Чем больше взаимодействий между процессами требуется для получения ответа на воздействие, тем большим будет время задержки.

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

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

Автор оригинала – Randy Stafford