Когда оптимизация преждевременна?

Я вижу, что этот термин часто используется, но я чувствую, что большинство людей используют его из-за лени или невежества. Например, я читал эту статью:

http://blogs.msdn.com/b/ricom/archive/2006/09/07/745085.aspx

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

Если бы это был я, говоря об этом для кода, который нам нужно написать, другие программисты тоже подумают:

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

или оба.

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

Что является более предпочтительным?

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

10 ответов

Оптимизация преждевременна, если:

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

  2. Вы делаете что-то срочное в чем-то, кроме сборки, и все еще беспокоитесь i++; i++; быстрее или i += 2... если это действительно так важно, вы бы работали на сборке и не тратили время на беспокойство по этому поводу. (Даже тогда этот конкретный пример, скорее всего, не будет иметь значения.)

  3. У вас есть предчувствие, что одна вещь может быть немного быстрее, чем другая, но вам нужно ее найти. Например, если вас что-то беспокоит StopWatch быстрее или Environment.TickCountЭто преждевременная оптимизация, поскольку, если бы разница была больше, вы, вероятно, были бы более уверены и не нуждались бы в ее поиске.

Если у вас есть предположение, что что-то может быть медленным, но вы не уверены, просто поставьте //NOTE: Performance? комментарий, и если вы позже столкнетесь с узкими местами, проверьте такие места в вашем коде. Я лично не беспокоюсь об оптимизациях, которые не слишком очевидны; Я просто использую профилировщик позже, если мне нужно.

Другая техника:

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

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

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

Оптимизация - это процесс повышения эффективности существующего кода (более высокая скорость и / или меньшее использование ресурсов).

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

Есть несколько этапов для хорошего программирования:

1) Разработайте решение и выберите хороший, эффективный алгоритм.

2) Внедрить решение в понятной, хорошо закодированной форме.

3) Протестируйте решение и посмотрите, соответствует ли оно вашим требованиям по скорости, использованию ОЗУ и т. Д. (Например, "Когда пользователь нажимает" Сохранить ", это занимает менее 1 секунды?" Если это занимает 0,3 с, вы действительно не тратить неделю на его оптимизацию, чтобы сократить это время до 0,2 с)

4) Если это не соответствует требованиям, подумайте почему. В большинстве случаев это означает, что перейдите к шагу (1), чтобы найти лучший алгоритм теперь, когда вы лучше понимаете проблему. (Написание быстрого прототипа часто является хорошим способом изучить это дешево)

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

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

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

  • Не помещать ненужный код в циклы. (Аналогично оптимизации удаления ненужного кода из существующих циклов, но это не требует написания кода дважды!)
  • Хранение промежуточных результатов в переменных, а не перерасчет вещей снова и снова.
  • Использование справочных таблиц для предоставления предварительно вычисленных значений, а не их вычисления на лету.
  • Использование структур данных соответствующего размера (например, хранение процента в байте (8 бит), а не в длинном (64 бита) будет использовать в 8 раз меньше ОЗУ)
  • Рисование сложного фона окна с использованием предварительно нарисованного изображения вместо рисования множества отдельных компонентов
  • Применяя сжатие к пакетам данных, вы намерены отправить по низкоскоростному соединению, чтобы минимизировать использование полосы пропускания.
  • Рисование изображений для вашей веб-страницы в стиле, который позволяет использовать формат, обеспечивающий высокое качество и хорошее сжатие.
  • И, конечно, хотя это технически не является "выбором", выбор правильного алгоритма в первую очередь!

Например, я просто заменил старый кусок кода в нашем проекте. Мой новый код никак не "оптимизирован", но (в отличие от оригинальной реализации) он был написан с учетом эффективности. Результат: мой работает в 25 раз быстрее - просто не тратя время. Могу ли я оптимизировать это, чтобы сделать это быстрее? Да, я мог бы легко получить еще 2-кратное ускорение. Буду ли я оптимизировать свой код, чтобы сделать его быстрее? Нет, 5-кратное улучшение скорости было бы достаточно, и я уже достиг 25-кратного. Дальнейшая работа на этом этапе будет просто пустой тратой времени на программирование. (Но я могу пересмотреть код в будущем, если требования изменятся)

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

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

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

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

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

Однако не переживайте, пока не найдете реальную проблему.

Оптимизация сложная. Рассмотрим следующие примеры:

  1. Принятие решения о внедрении двух серверов, каждый из которых выполняет свою работу, вместо внедрения одного сервера, который будет выполнять обе работы.
  2. Решил перейти с одной СУБД, а не другой, из соображений производительности.
  3. Принятие решения об использовании конкретного непереносимого API-интерфейса при наличии стандарта (например, использование специфических функций Hibernate, когда вам в основном нужен стандартный JPA), из соображений производительности.
  4. Кодирование чего-либо в сборке по соображениям производительности.
  5. Развертывание циклов по соображениям производительности.
  6. Написание очень быстрого, но неясного куска кода.

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

  1. Сконцентрируйтесь на правиле 80/20 - не рассматривайте ВСЕ возможные случаи, но наиболее вероятные.
  2. Не переоценивайте вещи без веской причины.
  3. Не пишите код, который не является понятным, простым и легко обслуживаемым, если с ним нет реальной, немедленной проблемы с производительностью.

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

Наличие (большого) опыта может быть ловушкой. Я знаю многих очень опытных программистов (C\C++, ассемблер), которые, как правило, слишком беспокоятся, потому что привыкли беспокоиться о тактах и ​​лишних битах.

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

Обратите внимание, что оптимизация не является бесплатной (как в пиве)

  • это занимает больше времени, чтобы написать
  • чтение занимает больше времени
  • тестирование занимает больше времени
  • отладка занимает больше времени
  • ...

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

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

Точно так же, как создателям библиотеки.NET не потребовалось никаких измерений, прежде чем они начали оптимизировать System.String. Они должны были измерить во время, хотя.

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

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

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

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

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

Когда у вас менее 10 лет опыта в программировании.

Другие вопросы по тегам