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

82

Как сказал Кнут,

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

Это то, что часто возникает в ответах на вопросы Stack Overflow на такие вопросы, как «какой механизм цикла является наиболее эффективным», «методы оптимизации SQL?» ( и так далее ). Стандартный ответ на эти вопросы с советами по оптимизации - профилировать ваш код и сначала посмотреть, не проблема, а если нет, то ваша новая техника не нужна.

Мой вопрос: если конкретная техника отличается, но не является особенно неясной или запутанной, может ли это действительно считаться преждевременной оптимизацией?

Вот статья Рэндалла Хайда «Ошибка преждевременной оптимизации» .

Nickf
источник
42
Это своего рода ирония, что многие люди, которые кричат ​​«Преждевременная оптимизация - это корень всех зол», сами преждевременно оптимизировали цитату: (продолжение)
некоторые
22
«Мы должны забыть о небольших эффективности, скажем , около 97% времени: преждевременная оптимизация есть корень всех зол Однако мы не должны упустить наши возможности в этой критической 3%.» (Дональд Кнут)
некоторые
2
Я думаю, что это сказал К.А. Хоар. Даже Кнут так говорит.
jamesh
1
да, Тони Хоар сначала сказал, что «преждевременная оптимизация - это корень всего зла», но Кнут процитировал / перефразировал его, добавив остальное, я полагаю
nickf
2
Хотя я согласен, что цитата - это вопрос, который чаще всего злоупотребляют и вырывают из контекста, он по определению всегда верен из-за «преждевременности» (однако чаще всего он используется неправильно как оправдание небрежного дизайна и кода). По определению, если оптимизация произошла в наиболее подходящий момент в процессе разработки, будь то во время проектирования или в любой другой момент, это не было «преждевременным».
Лоуренс Дол

Ответы:

103

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

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

  • Использование арифметики указателей вместо записи массива в C, включая использование таких идиом, как

    for (p = q; p < lim; p++)
    
  • Повторная привязка глобальных переменных к локальным переменным в Lua, как в

    local table, io, string, math
        = table, io, string, math
    

Помимо таких идиом, сокращайте путь на свой страх и риск .

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

  • Программа слишком медленная (многие забывают эту часть).

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

(Также допустима оптимизация для памяти.)

Прямой ответ на вопрос:

  • Если ваш «другой» метод затрудняет понимание программы , то это преждевременная оптимизация .

РЕДАКТИРОВАТЬ : В ответ на комментарии использование быстрой сортировки вместо более простого алгоритма, такого как сортировка вставкой, является еще одним примером идиомы, которую все понимают и ожидают . (Хотя, если вы напишете свою собственную процедуру сортировки вместо использования процедуры сортировки библиотеки, можно надеяться, что у вас есть очень веская причина.)

Норман Рэмси
источник
13
По вашим определениям; Если реализация быстрой сортировки сложнее для чтения и понимания, чем пузырьковая сортировка, это преждевременная оптимизация. Не можете оптимизировать под память? Попробуйте найти те же примеры для больших разреженных матриц. ИМХО, большая часть оптимизации должна происходить на этапе проектирования. я, е, очень рано.
SmacL
1
@frankodwyer: но увеличение указателя возможно быстрее, чем увеличение счетчика и использование нотации массива, и это было бы преждевременной оптимизацией.
Йоахим Зауэр,
5
@Norman: Хотя быстрая сортировка сейчас повсеместна, она не была тогда, когда впервые была изобретена, и поэтому QED была преждевременной оптимизацией, с которой автор не имел никакого отношения, верно?
Лоуренс Дол
5
@Software Monkey: Совершенно верно. Все исследования CS - пустая трата денег налогоплательщиков и должны быть немедленно прекращены.
Норман Рэмси,
11
Любой алгоритм сортировки, в том числе изобретенный вами, будет ясным и кратким, если он написан в виде отдельной функции с именем sortQuickly (...) с соответствующими комментариями.
илья н.
40

ИМХО, 90% вашей оптимизации должно происходить на стадии проектирования, исходя из текущих и, что более важно, будущих требований. Если вам нужно удалить профилировщик, потому что ваше приложение не масштабируется до требуемой нагрузки, вы оставили его слишком поздно, и IMO потратит много времени и усилий, не сумев исправить проблему.

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

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

SmacL
источник
6
Я не согласен с вашим выводом "слишком поздно". В основном профилирование необходимо, когда предположение не выполняется, и профилировщик необходим, чтобы сообщить вам, ЧТО допущение нарушилось. Например, я обнаружил, что «удалить символ в позиции 0» для StringBuffers в Java отлично работает для тестов junit, но ОЧЕНЬ медленно для больших строк. Я не подозревал об этом коде, пока профилировщик не определил его как виновника!
Торбьёрн Равн Андерсен,
7
Я согласен с тем, что «когда вам нужен профилировщик, уже слишком поздно», основываясь на моем опыте - большинство моих проблем с производительностью не являются единичными узкими местами, а распространяются на нескольких участников. Но с другой стороны, у меня есть серьезный опыт в области кода и затрат на низком уровне, и я бы инстинктивно избегал всего, что полагается на (значительно повторяющееся) удаление первого строкового символа. +1 за «оптимизацию во время проектирования».
peterchen
@peterchen просто из любопытства, что бы вы сделали для «удаления первого строкового символа».
Ghos3t 01
1
@ user258365: Грубая сила заключается в использовании строкового представления, которое не требует создания копии для подстрок. Это «почти тривиально» для неизменяемых строк с подсчетом ссылок. В качестве альтернативы, алгоритмические изменения, такие как замена (псевдокода) while (s[0]==' ') s = s.substring(1) for(i=0; i<s.len && s[i]==' '; ++i); s=s.substring(i)- но для этого уже необходимо знать потенциальные проблемы с производительностью (профилировщики - ценные инструменты для постоянного обучения здесь).
peterchen 01
@ ThorbjørnRavnAndersen, я работал консультантом, чтобы помочь команде завершить проект, но это было невозможно, потому что не планировалось серьезных проблем с производительностью (кроме кода спагетти). Предполагалось показать хронологическую диаграмму с историей всех пациентов. Был сделан один запрос для всех данных, например, Google Maps извлекает весь мир. Разработка плохого кода, ожидание профилирования позже привело к сбою проекта.
Педро Амарал Коуту
31

Если вы не профилировали, это преждевременно.

ДжаредПар
источник
3
Я согласен с идеей, лежащей в основе этого, но также: если реализация полностью не связана с циклами ЦП, получить измерение, которое можно воспроизводить и обобщать, сложно - и чем оно стабильнее, тем менее реалистично.
peterchen
1
Проблема, с которой я столкнулся с приведенным выше ответом, заключается в том, что он подразумевает, что вы не можете оптимизировать алгоритм, прежде чем кодировать его. Мой способ работы заключается в разработке алгоритма, отвечающего функциональным требованиям. Посмотрите, не нарушит ли он требований к производительности (например, высокий порядок сложности и вероятно попадет в большие наборы данных), и оптимизируйте алгоритм, прежде чем начинать его кодировать. Оптимизация - это просто доработка для достижения оптимального решения, часто наиболее эффективно это делается на стадии проектирования.
SmacL
2
Я не согласен. Кнут говорил о небольшой эффективности. Оптимизация часто происходит на этапе проектирования. Это включает в себя выбор надлежащих структур данных и алгоритмов, которые часто имеют большое влияние на производительность и не обязательно могут быть обменены позже.
haslersn 08
@haslersn: «Кнут говорил о небольшой эффективности» Дональд Кнут: «Общепринятое мнение, разделяемое многими сегодняшними разработчиками программного обеспечения, призывает игнорировать эффективность в малом; но я считаю, что это просто чрезмерная реакция на злоупотребления (...) установленных инженерных дисциплин: улучшение на 12%, легко достигается, никогда не считается незначительным (...) »
Педро Амарал Коуту
27

Мой вопрос: если конкретная техника отличается, но не является особенно неясной или запутанной, может ли это действительно считаться преждевременной оптимизацией?

Гм ... Итак, у вас есть две готовые техники, одинаковые по стоимости (одинаковые усилия для использования, чтения, изменения), и одна более эффективна. Нет, в таком случае не было бы преждевременным использование более эффективного.

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

Shog9
источник
3
Согласны, если вы знаете, что один алгоритм более эффективен для вашего варианта использования, обязательно используйте более эффективный. Если вы не знаете наиболее эффективный алгоритм, используйте то, что у вас есть, и профилируйте позже, чтобы убедиться, что это проблема.
grepsedawk
10

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

Есть разрыв между тем, чтобы сказать это и сделать это.

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

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

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

Так это была преждевременная оптимизация или нет?

Майк Данлэйви
источник
Мне нравится этот ответ, поскольку он иллюстрирует одну из основных проблем абстракции и обобщения. Когда вы обобщаете иерархию классов для поддержки более широкого диапазона вариантов использования, очень легко серьезно ухудшить производительность для наиболее типичных случаев использования. Также легко зафиксировать класс, который предоставляет заданную часть функциональности, без проверки того, предоставляется ли функциональность на приемлемом уровне производительности для масштаба предполагаемого использования.
SmacL,
1
«где простые концепции были бы менее элегантными, но вполне достаточными» Сложный код редко бывает более элегантным, чем простой код, когда простой код отвечает требованиям. (Хотя я бы сказал, что вы должны убедиться, что ваш простой код действительно взрывается с четким указанием неподдерживаемого состояния / ввода, если кто-то попытается выполнить его в более сложном случае.)
jpmc26
8

Во-первых, заставьте код работать. Во-вторых, убедитесь, что код правильный. В-третьих, сделайте это быстро.

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

Ватин
источник
8

С точки зрения базы данных, не рассматривать оптимальный дизайн на этапе проектирования в лучшем случае безрассудно. Базы данных не так легко реорганизовать. Если они плохо спроектированы (это то, что дизайн, который не учитывает оптимизацию, независимо от того, как вы могли бы попытаться спрятаться за ерундой преждевременной оптимизации), почти никогда не сможет восстановиться от этого, потому что база данных слишком проста для работа всей системы. Гораздо менее затратно правильно спроектировать с учетом оптимального кода для ожидаемой ситуации, чем ждать, пока не появится миллион пользователей и люди будут кричать, потому что вы использовали курсоры во всем приложении. Другие оптимизации, такие как использование расширяемого кода, выбор наиболее подходящих индексов и т. Д., Имеют смысл только во время разработки. Не зря так называется «быстро и грязно». Потому что он никогда не может хорошо работать, поэтому не используйте скорость вместо хорошего кода. Кроме того, откровенно говоря, когда вы понимаете настройку производительности в базах данных, вы можете написать код, который с большей вероятностью будет работать хорошо за то же время или меньше, чем требуется для написания кода, который не работает хорошо. Не тратить время на изучение того, что лучше всего работает при проектировании базы данных, - это лень разработчика, а не лучшая практика.

HLGEM
источник
7

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

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

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

В ответ на множество других комментариев по этому вопросу: выбор алгоритма! = Оптимизация

FredV
источник
6

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

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

Yfeldblum
источник
2
Фактически, изрядная часть «оптимизации» сводится к выбору правильного алгоритма для работы; это высокоуровневое мероприятие с высокоуровневыми результатами - это далеко от «небольшой эффективности» в цитате Кнута.
Shog9,
4

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

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

При написании кода (или запроса к БД) я стремлюсь написать «эффективный» код (т.е. код, который выполняет свою предполагаемую функцию, быстро и полностью с разумной простейшей логикой). Обратите внимание, что «эффективный» код не обязательно совпадает с «оптимизированным». код. Оптимизация часто вносит дополнительную сложность в код, что увеличивает стоимость разработки и сопровождения этого кода.

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

Крис Нава
источник
4

При программировании большое значение имеет ряд параметров. Среди них:

  • Читаемость
  • Ремонтопригодность
  • Сложность
  • Надежность
  • Правильность
  • Спектакль
  • Время разработки

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

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

Ола Эльдёй
источник
1
В приведенном выше списке отсутствует самый важный параметр обеспечения качества; Соответствие требованиям. Если часть программного обеспечения не соответствует требованиям целевой аудитории, все остальные параметры не имеют смысла. Если производительность неприемлема, требования не выполнены.
SmacL
3
Можно сказать, что это прикрывается правильностью. Кроме того, «производительность» в смысле «как можно быстрее» очень редко встречается среди требований, и даже точка зрения Олы, что это компромисс с другими потребностями, остается верной.
frankodwyer
4

Оптимизация может происходить на разных уровнях детализации, от очень высокого до очень низкого:

  1. Начните с хорошей архитектуры, слабой связи, модульности и т. Д.

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

  3. Оптимизируйте для памяти, пытаясь уместить больше кода / данных в кеш. Подсистема памяти в 10-100 раз медленнее, чем ЦП, а если ваши данные выгружаются на диск, это в 1000-10 000 раз медленнее. Осторожность с потреблением памяти с большей вероятностью принесет большую пользу, чем оптимизация отдельных инструкций.

  4. Внутри каждой функции надлежащим образом используйте операторы управления потоком. (Переместите неизменяемые выражения за пределы тела цикла. Поместите наиболее распространенное значение первым в переключателе / ​​регистре и т. Д.)

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

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

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

В большинстве случаев либо:

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

или же

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

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

Benjismith
источник
3

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

Например, чтобы добавить в список Нормана:

  • Использование конкатенации StringBuilder в Java (или C # и т. Д.) Вместо String + String (в цикле);
  • Избегайте цикла в C, например: for (i = 0; i < strlen(str); i++)(потому что здесь strlen - это вызов функции, каждый раз проходящий по строке, вызываемый в каждом цикле);
  • Кажется, что в большинстве реализаций JavaScript это тоже выполняется быстрее, for (i = 0 l = str.length; i < l; i++)и он все еще читается, так что хорошо.

И так далее. Но такие микрооптимизации никогда не должны происходить за счет читабельности кода.

PhiLho
источник
3

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

Я думаю, что «преждевременная оптимизация» невероятно субъективна.

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

Редизайн обходится дороже, чем оптимизация дизайна очевидными способами с самого начала.

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

Следовательно: НЕ оптимизация дизайна - это ИМО, запах кода сам по себе.

nbevans
источник
Дело в том, что узкие места часто возникают в тех частях кода, о которых вы никогда не думали, что это проблема. Профилирование не требует притворства и показывает фактические центры затрат программы. Лучше делать очевидные вещи с самого начала, но для всего остального есть профилирование.
Крис Смит
2

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

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

И продолжает:

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

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

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

... а затем еще немного о важности инструментов профилирования:

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

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

Тем не менее, это была цитата в пользу правильно примененных микрооптимизаций при использовании опытным человеком, держащим профилировщик. Сегодняшний аналогичный эквивалент может выглядеть так: «Людям не следует слепо пытаться оптимизировать свое программное обеспечение, но настраиваемые распределители памяти могут иметь огромное значение при применении в ключевых областях для улучшения локальности ссылок» или « Рукописный код SIMD с использованием SoA rep действительно сложно поддерживать, и вы не должны использовать его повсюду, но он может потреблять память намного быстрее, если применять его соответствующим образом опытной и управляемой рукой ».

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

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

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


источник
1

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

PolyThinker
источник
1

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

Даниэль Аугер
источник
1

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

Камиль Кисиэль
источник
0

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


источник
0

Как я писал по аналогичному вопросу, правила оптимизации следующие:

1) Не оптимизируйте

2) (только для экспертов) Оптимизировать позже

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

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

Еще один вопрос, который следует задать себе при оптимизации: «делаю ли я здесь эквивалент оптимизации для модема со скоростью 300 бод?» . Другими словами, закон Мура сделает вашу оптимизацию неуместной в ближайшее время. Многие проблемы масштабирования можно решить, просто добавив больше оборудования.

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

edit: Между прочим, что касается связанной статьи, я бы поставил под сомнение многие сделанные предположения. Во-первых, неправда, что закон Мура перестал работать в 90-е годы. Во-вторых, не очевидно, что время пользователя более ценно, чем время программиста. Большинство пользователей (мягко говоря) в любом случае не лихорадочно используют каждый доступный цикл ЦП, они, вероятно, ждут, пока сеть что-то сделает. Плюс к этому есть альтернативные издержки, когда время программиста отвлекается от реализации чего-то другого, чтобы сэкономить несколько миллисекунд на том, что программа делает, пока пользователь разговаривает по телефону. Все, что длиннее, обычно не является оптимизацией, это исправление ошибок.

Франкодвайер
источник