Определение проблемы

Сначала поймайте кролика.

Рецепт приготовления тушеного кролика

Прежде чем что-то оптимизировать, нам нужно определить, что же именно мы оптимизируем. В противном случае — это просто «стрельба по воробьям». Прежде чем искать проблему, нам нужно четко определить, в чем конкретно она заключена. Иначе, в самом прямом смысле, мы не знаем, что делам.

Часто определения проблем уже найдены за нас. Это как рецепты. Много людей проходит теми же тропами и оставляет огромный массив знаний для нас. Нет ничего необыкновенного или сложного; нужно всего лишь в точности следовать приведенным инструкциям.

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

Приложение WidgetFactoryServer работает слишком медленно.

Что значит медленно?

  • Это может значить, что приложение достаточно медленное, чтобы его работа оказалась едва заметна человеку (например, более 350 миллисекунд).
  • Либо, что пользователь WFS получает ошибку time out, ожидая ответа сервера.
  • Или эта медлительность как-то проявляется во время использования тех или иных компонентов.

«Слишком медленно» относится к измерению реального времени (walltime) загрузки чего-либо. Другими словами, медленно – это когда время работы можно измерить буквально по часам на стене. В реальном времени обычно измеряют две вещи: вычисления на локальном компьютере или запрос данных из локального или удаленного хранилища.

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

WidgetFactoryServer является транзакционным. Он получает запросы и генерирует ответы. Его работа, скорее всего, завязана на процессоре.

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

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

Реальная оптимизация оказалась практически скучной. Программист Вася провел профилирование, которое показало, что самым «прожорливым» местом является какой-то замысловатый цикл, который, скажем, генерирует каждый раз заново список WidgetTypes или постоянно пересчитывает значение, которое можно посчитать один раз. Как только он это увидел, исправление проблемы было внесено незамедлительно, а время выполнения программы значительно снизилось. Все счастливы.

Тут-то и начинаются проблемы

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

Вася обнаруживает, что стоит всего лишь убрать кусок кода из программы – и мы выигрываем 10% времени ее выполнения. Он, естественно, проводит следующие две недели, оптимизируя программу по тому же шаблону. «Цикл WidgetTypes слишком медленный!» — говорит он всем своим коллегам. Конечно, это может быть и правдой, но разве это важно? Критичны ли все эти остальные случаи? Влияли ли они вообще на показатели? Скорее всего, нет. Так появляется на свет «народная медицина». В конечном итоге это решение работает только один раз.

Совет «определи проблему, а потом исследуй ее», — это не просто добавочные колесики к велосипеду, которые можно выбросить сразу же после того, как научишься нормально ездить сам. Это то, что нужно проделывать каждый раз, когда ты хочешь что-либо оптимизировать или проверить, каждый раз все сначала, проверяя и тестируя каждое предположение.

Электронные системы поразительно сложны. Очень глупо стричь все под одну гребенку, просто один раз выловив ошибку в одном месте и получив результат. «Мы настроили по два одновременных процесса на каждое ядро процессора, благодаря чему увеличили скорость вот на столько», — звучит хорошо и правильно, но в таком случае нельзя сказать: «Чтобы скорость выросла вот настолько-то, просто сделайте так, чтоб число процессов не превышало двукратно количество ядер процессора». Это не одно и то же. Как бы ни хотелось.

Однажды я выполнил обобщение из одной точки данных. Никогда больше не сделаю этого!

Ахиллес Логик, Lauren Ipsum

Опыт прошлых оптимизаций нисколько не бесполезен. Он может подсказать, куда смотреть. Но не стоит ему доверять настолько же, как мы доверяем, например, гравитации. Если кто-то показывает вам что-то, расспросите подробнее. Если кто-то показывает вам тест производительности, отыщите принцип, по которому это работает. Если вам говорят «X слишком медленный» или «Y слишком быстрый», возьмите это на заметку. Учитывайте все, а потом проводите свое исследование сами. Каждый раз.

Профессиональный фестиваль "Российские интернет-технологии" — весь спектр индустрии веб-разработки от системного администрирования до управления проектами и высоконагруженных систем, а также клиентское программирование, базы данных и системы хранения, тестирование и качество. Всё это вокруг бесплатной технологической выставки.

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

Хотите узнать больше о наших конференциях?