Правильно ли я понимаю преждевременную оптимизацию? - PullRequest
5 голосов
/ 09 июня 2010

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

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

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

Ответы [ 3 ]

20 голосов
/ 09 июня 2010

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

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

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

Вам не нужен код, который не работает оптимально.


Цитата, которую я не смог вспомнить, от Мич Равера:

Если это не работает, не имеет значения, насколько быстро это не работает.

5 голосов
/ 09 июня 2010

Мы должны забыть о малой эффективности, скажем, в 97% случаев: преждевременная оптимизация - корень всего зла.- Hoare

В то время как @John Saunders прибивает его, применение только TDD может не полностью решить ваши проблемы.Я придерживаюсь TDD, и когда вы делаете TDD правильно и если вы можете эффективно применять рефакторинг, вы, как правило, получаете гораздо более простой код и то преимущество, которое, как вы знаете, работает.Никаких аргументов там нет.

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

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

Ошибка в том, что «преждевременная оптимизация» - это то же самое, что и «Забота о производительности "не должна направлять разработку программного обеспечения.- Randall Hyde

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

Некоторые статьи

1 голос
/ 07 января 2016

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

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

Более полная цитата:

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

Общепринятая мудрость, разделяемая многими современными разработчиками программного обеспечения, призывает игнорировать эффективность в малом;но я полагаю, что это просто чрезмерная реакция на злоупотребления, которые, как они видят, практикуются программистами, которые не могут отлаживать или поддерживать свои «оптимизированные» программы.В устоявшихся инженерных дисциплинах легко достижимое улучшение на 12% никогда не считается незначительным;и я считаю, что та же точка зрения должна преобладать в разработке программного обеспечения.Конечно, я бы не стал делать такую ​​оптимизацию на одноразовой работе, но когда речь идет о подготовке качественных программ, я не хочу ограничиваться инструментами, которые лишают меня такой эффективности.

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

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

После программист знает, какие части его подпрограмм действительно важны, и такое преобразование, как удвоение циклов, будет целесообразно,Обратите внимание, что это преобразование вводит операторы go to, как и некоторые другие оптимизации цикла.

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

В основе этого создания Кнута «преждевременного оптимизатора» лежит:

  1. Оптимизация на основе догадок / суеверий / человеческой интуиции без прошлого опыта или измерений (оптимизация вслепую, фактически не зная, что вы делаете).
  2. Оптимизация способом, который экономит пенни за фунты (неэффективные оптимизации).
  3. Поиск абсолютного пика эффективности для всего.
  4. Поиск эффективности на некритических путях .
  5. Попытка оптимизировать, когда вы едва можетеподдерживать / отлаживать ваш код.

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

Такие вещи, как разработка через тестирование и основное внимание к дизайну интерфейса, не были освещены в статье Кнута. Это более современные концепции и идеи. Он был сосредоточен на реализации в основном.

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

Если мы попытаемся применить современную интерпретацию Кнута, я бы добавил туда «корабль». Даже если вы оптимизируете истинные критические пути своего программного обеспечения с помощью измеряемых коэффициентов усиления, самое быстрое программное обеспечение в мире бесполезно, если оно никогда не поставляется. Помня об этом, вы должны идти на более разумные компромиссы.

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

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

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

Например, не проектируйте систему частиц с клиентскими зависимостями для интерфейса Particle. Это не оставляет места для оптимизации, когда у вас есть только инкапсулированное состояние и реализация одной частицы для работы. В этом случае вам может потребоваться внести каскадные изменения в вашу кодовую базу для оптимизации. Гоночный автомобиль не может использовать свою скорость, если длина дороги составляет всего 10 метров. Вместо этого проектируйте в направлении интерфейса ParticleSystem, который объединяет миллион частиц, например, с операциями более высокого уровня, которые, когда это возможно, имеют дело с большими частицами. Это оставляет вам много места для оптимизации, не нарушая ваши проекты, если вы обнаружите, что вам нужно оптимизировать.

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

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

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

...