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

#1. Что такое оптимизация?

Оптимизация - модификация системы для улучшения её эффективности.

Или

Оптимизация - приведение программы от состояния «не устраивает», в состояние «пойдёт», по параметрам производительности.

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

Производительность может измеряться как в количестве потребляемых ресурсов приложением, например сколько оно потребляет ОЗУ, насколько сильно напрягает CPU, или вообще, специфичной, для домена, метрике.
Например: максимальное количество выданных займов в одну единицу времени.
Или сколько мы можем обрабатывать заказов в пиковые праздничные дни.

#2. Связанные понятия

1) Bottleneck или бутылочные горлышки

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

Обычно проблемы в рамках всего приложения создают именно bottleneck'и. Чтобы их отследить, необходимо использовать профилировщики и / или бенчмарки.

Отличными примерами bottleneck'ов являются любые http запросы и ожидания ответа от каких-то внешних (и внутренних порой!) сервисов. Работа с базой данных, например вызов хранимой процедуры или выполнение сложного запроса.

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

2) Tradeoff или компромиссы

Оптимизация - это далеко не про создание перфоманса из воздуха. Зачастую приходится выбирать из нескольких зол.

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

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

Конечно, обычно можно настроить размер cache, но увеличенное потребление ОЗУ все-таки может стать проблемой.

Tradeoff - выбор самого оптимального, в рамках вашего контекста, решения.

Контекст может быть таким, что необходимо уменьшить потребление ОЗУ у сервиса, при этом про увеличение производительности может речи не идти.

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

#3. Когда следует заниматься оптимизацией

Желательно никогда.

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

А если все-таки такой запрос от бизнеса пришёл - необходимо помнить следующее:

1) Заранее знай, к какому результату вы хотите придти

Я на это намекал, когда писал про tradeoff.

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

Стоит ли оптимизировать несколько дней определённый участок кода ради прироста в несколько миллисекунд?
Ответ: да. Если этого требует ваш бизнес.
В остальных случаях не стоит.

Чтобы часто не задаваться вопросом: «А стоит ли этот код оптимизировать?».
Необходимо знать, что именно необходимо оптимизировать.
Возможно объект оптимизации находится в сервисе, которым занимается другой сотрудник. В таком случае, скорее всего, можно избежать работы полностью или частично.

«Лучший код тот, который не был написан»

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

2) Преждевременная оптимизация - корень всех зол или бед

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

Когда вы это делаете - вы уже нарушаете принципы YAGNI и скорее всего KISS.
Следуя которому вы стараетесь писать максимально простой код.

А оптимизация это зачастую не про простой код.

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

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

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

Поэтому необходимо помнить, что:

3) Оптимизация - твой враг

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

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

Если три правила активно нарушать, то рано или поздно случится следующее:

Как выглядят попытки программиста что-то оптимизировать
Как выглядят попытки программиста что-то оптимизировать

Комментарии (14)


  1. MentalBlood
    24.12.2022 12:16
    +2

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


    1. speshuric
      25.12.2022 02:21
      +4

      Ага. А также ОС, СУБД, системы кеширования, нагруженные системы, ФС, рантаймы (аллокаторы памяти, JIT, сборщики мусора и т.п.), игры, мультимедиа (обработка звука, изображений, видео, рендеринг), ПО для массовых вычислений. И еще 100500 видов ПО.


  1. Nova_Logic
    24.12.2022 12:40
    +4

    Ага, а потом прилетит SRE/DevOps, у которого будет зад в огне, когда увидит, что ради простоты , разработчик решил не батчами селекты/апдейты делать, а просто так, без оптимизаций, в результате чего простой не оптимизированный код насилует всю огромную таблицу с I/O 1,5 гиг в секунду


    1. GTD01
      24.12.2022 23:16
      -1

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


  1. funca
    24.12.2022 12:41
    +6

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

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


  1. ZvoogHub
    24.12.2022 13:38
    +12

    Дай мне мужество чтоб отрефакторить баги которые критичны,

    дай мне смирение чтоб не трогать то что работает,

    дай мне мудрость чтоб отличить одно от другого.


  1. mirwide
    24.12.2022 13:55
    +2

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

    Нужна или нет оптимизация неплохо считается в деньгах. Например, если команда из 10 человек пишет сервис который занимает 1 сервер, разработка стоит дороже эксплуатации. А если сервис занимает уже 2-3 стойки, то зарплата разработки на порядок меньше расходов на инфраструктуру. Получается, что на начальном этапе развития сервиса на оптимизацию можно забить, что потом вылезет под нагрузкой. Это не отменяет, что разработка, в лице архитектора должна думать на шаг вперед, правильно строить архитектуру, выбирать стэк, ревьювить решения соизмеримо нагрузке планируемой.


  1. kellas
    24.12.2022 17:38
    +9

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

    Этот тезис про преждевременную оптимизацию только как отмазку используют.

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

    Не надо такое советовать. Эту статью прочитают сотни недомидлов и радостные продолжат говнокодить ещё больше.


    1. Kolonist
      24.12.2022 22:38
      +3

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

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


      1. kellas
        25.12.2022 07:20

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


      1. funca
        25.12.2022 19:06
        +1

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

        Какие-то вещи может не вывозить команда, просто вследствие недостатка квалификации.

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


  1. a-tk
    24.12.2022 17:54
    +9

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


  1. dkuzminov
    25.12.2022 09:22
    +2

    Оптимизация - модификация системы для улучшения её эффективности.

    Или

    Оптимизация - приведение программы от состояния «не устраивает», в состояние «пойдёт», по параметрам производительности.

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

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


  1. AshBlade
    25.12.2022 12:30
    +1

    Сразу вспомнилось выражение Д. Кнута: "Преждевременная оптимизация - корень всех зол". Но не все вспоминают контекст:

    There is no doubt that the grail of efficiency leads to abuse. Programmers waste enormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered. We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil

    Иначе говоря, оптимизация зло - когда мы оптимизируем эти 3%. (Чем грешу порой и сам)

    Ссылка на статью: https://cowboyprogramming.com/files/p261-knuth.pdf