-
Какой идиот это написал? (фамилию я знаю)
Или спрошу иначе: почему эта фраза трактуется как "оптимизировать не нужно", "думать про то, как твой код будет работать в смысле скорости - не нужно"?
Или я что-то не понимаю? Меня просто поражает постоянно приводимый этот аргумент, когда указываешь множественный вызов каких-то методов/функций с одинаковыми параметрами.
В итоге когда выясняется, что "всё работает медленно" - не удаётся даже заоптимизировать код, потому как он равномерно выполняется, каждая вложенная функция как бы небольшую часть времени занимает.
-
-
Это я читал.
Но что я не понимаю?
-
Сейчас модно делать так: 1. Сначала пишешь тест. 2. Потом реализацию проходящую этот тест (как угодно: хоть с goto). 3. Когда тест пройдет, проводишь рефакторинг и делаешь оптимизации.
-
Наверно, здесь ключевое слово - "преждевременная"
-
KSergey © (10.11.16 10:43) [2]
Гугль: "практика программирования первый принцип оптимизации - по возможности избегать ее"
Оптимизацию следует начинать с поиска узких мест при помощи профилирования программы. Оптимизировать при проектировании или при написании кода стоит ровно в одном случае, когда опыт подсказывает быстрые решения (например, не использовать TMemo для поиска строк в файле).
-
Что в итоге. Имеем софт, который работает медленно (в смысле требуется на порядок быстрее). Профилирование показывает, что нет участков вода, которые можно оптимизировать в том смысле, что все ровным слоем размазано, нет явных мест, занимающих 90% времени.
Всё переписать - ресурсов нет. Всё после переписывания перетестировать - тем более нет ресурсов. новый код пишется по тому же принципу.
Любые указания на то, что вот в этом месте нового кода можно вот это сделать хоть как-то оптимальнее, дабы не плодить размазывание "производительности" натыкаются на идиотский аргумент от гуру "преждевременно". Ну гуру же сказал.
Что я не понимаю? где я ошибаюсь?
-
На мой взгляд, ты ошибаешься в том, что "любые указания на то, что вот в этом месте нового кода можно вот это сделать хоть как-то оптимальнее" спасут ситуацию в этом случае. Оно как было размазано ровным слоем, так и останется, за исключением того места, на которое ты указал, оптимизация которого не сыграет никакой роли, раз уж оно ровным слоем.
-
Надо менять всю систему
-
Кнут написал это для умных программистов, которые понимают, что оптимизация - это замена краткого и понятного кода на более быстрый, но и более длинный и/или хуже читаемый. Этого преждевременного ухудшения читаемости (усложнения) он и советует избегать. Он не взял в расчет, что ленящийся думать (но не печатать) программист может написать вместо краткого кода более длинный, но тупой, да при этом еще и более медленный. Его замена на более понятный и согласованный с принципом DRY код - рефакторинг, оптимизацией даже не являющийся. Понятность и DRY - прежде скорости, но уж если они заодно - сам бог велел...
-
Надо для начала определиться, что такое "быстро" и что такое "медленно".
Пример: юзер нажал кнопку, программа выполнила кучу операций и через 1/4 секунды выдала результат.
Это быстро или медленно?
С практической точки зрения - нормально. Юзер эти 250 мс даже и не заметит.
Надо ли оптимизировать эту кучу операций?
Видимо, оптимизация в данном случае смысла не имеет. Поэтому, если мы провели оптимизацию еще на этапе первоначального написания кода, то мы просто зря потратили время.
-
Всё очень просто. Есть структуры данных, их немного. Эта единственная область теоретически обоснованная. И в ней всё понятно что и когда выбирать. Вставка, удаление, поиск. 3^3 всего 27 их должен знать каждый. Их надо применять сразу. Остальное можно оставить напотом. Так как для низ нет критерия быстро или медленно. Быстро и медленно вводится только от параметра и то только в пределе. О-большое или теэта-большая. Поэтому о скорости мы всегда говорим относительно алгоритмов. А как известно структуры связаны с алгоритмами.
-
Есть госты по эргономике если операция длится дольше 0.1 секунды то должна быть индикация или сигнализация.
-
а под оптимизацией ваще-то не только скорость подразумевается, у меня в компиле ваще можно регулировать, в какую сторону приоритетить - скорости или ресурсов.
Кнут енто говорил лет тыщу назад и во-первых, он всего лишь человек, и во-вторых каждый пишет как хочет.
Лично я вовсю преждевременно оптимизирую. И как-то менее глюкаво выходит в итоге.
-
I. Сначала про сабж.Имхо писать надо балансируя время разработки и качество. Надо вовремя понимать, что что-то начало тормозить. Зачастую простого анализа достаточно, чтобы общую производительность поднять изрядно. Т.е. имхо надо править то, что реально тормозит. А в остальном пытаться оставлять понятный человеку код. Конечно не верно забивать на оптимизацию, а потом хвататься за волосы. II. Теперь из жизни1. Пример оптимизации. Есть штатная функция StringReplace (у меня Delphi2007). Всем хороша с виду. Но была у меня задача: 100тыщ мелких строк объединить в одну, при этом в каждой из строк один паттерн заменить на другой. Стало тормозить на порядок. Чудеса! Долго думал. Оказалось виновата StringReplace. Она имеет сложность N^2 не меньше (код посмотрите). Пришлось написать свою. Как вышел на StringReplace (кто бы мог подумать, что штатная функция может быть во всем виновата?!). Пользуюсь такой программой (не помню где брал): Sampling Profiler 1.7.4.0. Copyright 2005-2009 / Creative IT - Eric Grange В результате анализа веса использования тех или иных функций вышел на StringReplace. Покопайся. Может у тебя где-то пузырьковая сортировка используется для больших объемов. 2. Я это к чему. Бывают такие места, которые используются в программе миллионы раз, сами состоят из нескольких строк, но т.к. используются многократно, то их оптимизация дает эффект. Сравни ради интереса скорость выполнения кода. Все дело в наличии SEH. У меня были случаи, что подобная оптимизация давала изрядный эффект. var
I: Integer = 0;
procedure WithSEH(J: Integer);
begin
if J < I then
raise Exception.Create('wrong '+IntToStr(J));
end;
procedure NoSEH(J: Integer);
procedure Err();
begin
raise Exception.Create('wrong '+IntToStr(J));
end;
begin
if J < I then
Err;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
K: Integer;
FC, PC1, PC2: TLargeInteger;
begin
QueryPerformanceFrequency(FC);
QueryPerformanceCounter(PC1);
for K := 0 to 500000000 do
WithSEH(K);
QueryPerformanceCounter(PC2);
ShowMessage(FloatToStrF((PC2 - PC1) / FC, ffNumber, 4, 10));
QueryPerformanceCounter(PC1);
for K := 0 to 500000000 do
NoSEH(K);
QueryPerformanceCounter(PC2);
ShowMessage(FloatToStrF((PC2 - PC1) / FC, ffNumber, 4, 10));
end;
-
Оптимизация оптимизации рознь. Например - у нас есть довольно сложный алгоритм, который вначале разрабатывался исходя из стабильности и читабельности, потом переписали под максимальное быстродействие - с целыми числами и почти 100% использованием разрядной сетки вместо дробных и так всякими заморочками. Если бы делали оптимизацию сразу - то это очень сильно бы усложнило задачу. С другой стороны - если есть обычный код, без особенных заморочек, то почему бы сразу не применить известные методы?
Всё есть яд и всё - лекарство.
-
> Всё есть яд и всё - лекарство. >
Соглашусь. А подобные советы Кнута или кого ещё нельзя выдергивать из контекста.
-
> Юрий Зотов © (10.11.16 18:39) [10] > Надо для начала определиться, что такое "быстро" и что такое "медленно".
Уважаемый ЮЗ! Это совсем другая тема и нет смысла её сюда приплетать. Как я изначально указал, есть софт, скоростью работы которого уже недовольны (т.е. требуется на порядок быстрее объективно, и это не пользовательский интерфейс), но софт развивается функционально, естественным образом замедляясь ввиду добавления нового кода.
Так что уже определились: софт работает недопустимо медленно.
-
"Преждевременная оптимизация — корень всех зол"
по сравнению с преждевременной эякуляцией это просто пустяк.
-
> KSergey © (11.11.16 09:16) [17]
> Это совсем другая тема и нет смысла её сюда приплетать. > Как я изначально указал, есть софт, скоростью работы > которого уже недовольныПеречитайте [0]. Вот как раз ИЗНАЧАЛЬНО (т.е. в сабже) Вы никакого конкретного софта НЕ указали, а только процитировали известную фразу и высказались по ее поводу. Причем высказались обобщенно, не указав, опять же, никакого конкретного случая. Соответственно, обсуждение в ветке пошло в заданном Вами же плане - вообще, а не по Вашей проблеме конкретно. Поэтому претензии на этот счет Вам следует предъявлять самому себе. По поводу [6] совет такой: гуру либо прав, либо неправ. Дождитесь результата. По поводу тормозов, которые "размазаны тонким слоем". Когда-то пришлось мне оптимизировать код, в котором тормоза были именно "размазаны тонким слоем". Обращало на себя внимание то, что во многих местах длинными цепочками вызывалась куча геттеров. Примерно так: getA.getB.getC...getX.getY.getZ Причем из кода было ясно, что между такими вызовами значение Z не меняется - то есть, результат этой цепочки всегда будет один и тот же. Спрашивается - а зачем тогда каждый раз выполнять код всех геттеров? Надо выполнить каждую подобную цепочку один раз, а результат закэшировать. Хуже уж точно не станет, а далее посмотрим. Что и сделал, потратив совсем немного времени. Результат почти ошеломил - скорость тут же выросла примерно в 50 раз и была признана достаточной. Это я к тому, что "тормоза тонким слоем" могут получиться, в том числе, из-за того, что во многих местах вызывается инвариантный код (любой, не только геттеры). Сам по себе этот код может быть и не особо медленным, но в сумме дает те самые "размазанные тормоза". Не Ваш ли это случай?
|