-
Какой идиот это написал? (фамилию я знаю)
Или спрошу иначе: почему эта фраза трактуется как "оптимизировать не нужно", "думать про то, как твой код будет работать в смысле скорости - не нужно"?
Или я что-то не понимаю? Меня просто поражает постоянно приводимый этот аргумент, когда указываешь множественный вызов каких-то методов/функций с одинаковыми параметрами.
В итоге когда выясняется, что "всё работает медленно" - не удаётся даже заоптимизировать код, потому как он равномерно выполняется, каждая вложенная функция как бы небольшую часть времени занимает.
-
-
Это я читал.
Но что я не понимаю?
-
Сейчас модно делать так: 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 раз и была признана достаточной. Это я к тому, что "тормоза тонким слоем" могут получиться, в том числе, из-за того, что во многих местах вызывается инвариантный код (любой, не только геттеры). Сам по себе этот код может быть и не особо медленным, но в сумме дает те самые "размазанные тормоза". Не Ваш ли это случай?
-
> что во многих местах длинными цепочками вызывалась куча > геттеров. Примерно так: > getA.getB.getC...getX.getY.getZ > Причем из кода было ясно, что между такими вызовами значение > Z не меняется - то есть, результат этой цепочки всегда будет > один и тот же. ... > Что и сделал, потратив совсем немного времени. Результат > почти ошеломил - скорость тут же выросла примерно в 50 > раз и была признана достаточной.
Большое спасибо вам за конкретный пример. На самом деле речь всегда именно про это (для меня). "Зачем вот тут вызываешь функцию 28 раз? зачем вот тут навтыкал проверки одних и тех же параметров во всех 100 методах?" "Ты занимаешься преждевременной оптимизацией, а кнут (едрит его налево!) сказал..."
Спасибо, что внесли конкретику.
От того я на этого кнута и зол, ибо, по-моему, фигню он сморозил.
Единственное, в отличии от вас я не переделывал код для проверки реального влияния, но должна же быть разумность при написании кода, епты!
-
> Зачем вот тут вызываешь функцию 28 раз
Надо смотреть функцию. Она может возвращать разный результат или может выполнять какие-то побочные действия - тогда надо вызывать. И если надо, то стоит подумать над оптимизацией этой функции.
> навтыкал проверки одних и тех же параметров во всех 100 методах
Опять же, надо смотреть, могут ли значения параметров измениться между двумя проверками. Причем, неплохо вынести проверки в отдельный метод, даже если этот метод в итоге будет вызван всего один раз (а если много раз, то это тоже повод подумать над его оптимизацией).
Причем, тормоза в функции и/или в отдельном методе проверки параметров - это уже тормоза сосредоточенные, а не размазанные.
-
> KSergey © (11.11.16 11:06) [20]
Попробуйте программу погонять под указанным мною SampleProfile'ом или его аналогом. Результат может удивить. Хотя, конечно, статическую оптимизацию никто не отменял - и без выполнения программы можно найти много полезного.
-
Без правильной архитектуры приложения заниматься оптимизацией бессмысленно. Но, если архитектура выстроена ровно - заниматься оптимизацией в 95 процентов случаев даже не придется.
-
> Rouse_ © (11.11.16 12:03) [23]
Правильная архитектура, это как правильное решение - не всегда сразу понятно, насколько оно правильное.
-
Юрий Зотов © (11.11.16 10:38) [19]
"Обращало на себя внимание то, что во многих местах длинными цепочками вызывалась куча геттеров. Примерно так: getA.getB.getC...getX.getY.getZ Причем из кода было ясно, что между такими вызовами значение Z не меняется - то есть, результат этой цепочки всегда будет один и тот же. ... Что и сделал, потратив совсем немного времени. Результат почти ошеломил - скорость тут же выросла примерно в 50 раз и была признана достаточной. "
"Аналогичный случай" (С). Ошеломлен не был потому, что подозревал после просмотра результатов в профайлере, но все же был удивлен. :-) С тех пор на автомате везде так пишу. Цена, обычно - это объявление одной переменной. Впрочем, я подобные вещи преждевременной оптимизацией не считаю.
-
не нужно понимать буквально
> "Преждевременная оптимизация — корень всех зол"
-
Какие же вы суперзадачи решаете, если на современных компьютерах имеет проблемы с быстродействием. Завидую.
-
> Внук © (11.11.16 13:01) [27] > Какие же вы суперзадачи решаете, если на современных компьютерах > имеет проблемы с быстродействием. Завидую.
Например, массовый перерасчет выплат всем пенсионерам в регионе (скажем, в Москве).
Тут не завидовать надо, скорее - сочувствовать. :o)
-
> Юрий Зотов © (11.11.16 13:15) [28]
Я так и подозревал, что все проблемы от пенсионеров :)
-
> Внук © (11.11.16 13:01) [27]
Испортить можно все, что угодно. Современный компьютер исключением не является :)
-
> DayGaykin © (11.11.16 12:13) [24] > > > Rouse_ © (11.11.16 12:03) [23] > > Правильная архитектура, это как правильное решение - не > всегда сразу понятно, насколько оно правильное.
Ты вспомни как я ГСИ писал, почти месяц ни одной строчки кода - сидел только схемы рисовал. А результат - в багтрекере ошибок всего 8 процентов от общей лавины. Оть так-то. И оптимизацию только в узком месте делал - там где FTS первого уровня зачитывался с диска.
-
Писала программу. Решала в лоб. Кучей if, case и т.д. Оптимизировать время не было. Программа делала то, что надо, за полторы минуты. На замечания, что программа не оптимизирована плевала. работает же. И довольно быстро. Оптимизация нужна не везде, не всегда и не всем.
ИМХО! очень, очень ИМХО!
-
> manaka © (12.11.16 12:30) [32]
У нас на работе программист: - Страница открывается 70 секунд - это нормально и быстро ещё.
А чтобы выполнить работу, сотрудникам необходимо открыть страницу 120 раз в день (в пиковые дни). Т. е. два часа сотрудники просто ждут. Это же ужасно.
-
> Rouse_ © (11.11.16 14:05) [31]
Я больше запомнил твой метод принятия правильных решений: Принимаешь решение и считаешь его правильным.
-
> DayGaykin © (12.11.16 13:03) [34] > > > Rouse_ © (11.11.16 14:05) [31] > > Я больше запомнил твой метод принятия правильных решений: > Принимаешь решение и считаешь его правильным.
Я разве хоть раз ошибся? :)
-
> Страница открывается 70 секунд - это нормально и быстро > ещё.
Знакомо ) Иногда разработчики сидят на порезанных и фейковых данных, пишут запросы, у них все летает - таблички на пару тысяч строк. Деплоим - по минуте висит. И начинаем искать куда и какой индекс залепить.
-
Хуже, когда разработчики начинают оптимизировать то, где больше пары тысяч строк не может быть в принципе.
Как писали Миллсап с Хольтом, оптимизировать надо важные для бизнеса операции, а не все подряд гайки крутить, только потому, что они крутятся.
-
2 Игорь Шевченко © (12.11.16 21:43) [37] Ну при чём тут количество строк, Игорь? В каких-то случаях оптимизация нужна и в десятке/сотне строк. Если они выполняются в некоем цикле.
-
> метод принятия правильных решений: > Принимаешь решение и считаешь его правильным. ! а как иначе - вначале принял, а потом считаешь не правильным, а зачем тогда принимал? ;)
-
> NoUser © (13.11.16 02:23) [39]
Не сразу дошло:)
-
> Игорь Шевченко © (12.11.16 21:43) [37] > Хуже, когда разработчики начинают оптимизировать то, где > больше пары тысяч строк не может быть в принципе. > > Как писали Миллсап с Хольтом, оптимизировать надо важные > для бизнеса операции, а не все подряд гайки крутить, только > потому, что они крутятся.
Во-во, только не все это понимают. Я Пете Абрамову однажды писал проект (сервис + конфигуратор) он передал его заказчику а там местный "кодер" решил сервис поправить, все поломал. Вызывают, приезжаю, смотрю код - волосы дыбом - ты зачем сюда вообще полез? Ты сервисы то писать вообще умеешь, спрашиваю? Отвечает - ну я заоптимизировать хотел как лучше. И отладочные из сервиса через Writeln выводит - ппц.
-
Во вспомнил, даже кусок этого модуля откопал. Там ситуация была что Петя просил сделать маленький и шустрый сервис - я все на API накатал, а этот чудик (кодер) увидел что синхронизация нитей делается не по феншую, т.е. без вызова TThrad.Synchronize() ну и отцепил мою синхронизацию через SendMessage в нить сервиса, переписав на Synchronize. А т.к. TService не использовался, Synchronize пыталась влезть в основную нить приложения, которая предназначена для работы с SCM и висит в суспенде 99.9 десятых процентов времени, причем для лога встроил Wrinteln('Начало синхронизации');
Это была феерия :)
-
> Rouse_ © (13.11.16 11:48) [42]
Саш, я старался тестовый пример в после 14 писал, а никакой реакции)))
Скажи, вот ты стараешься избегать SEH как в моем примере?
-
> Тимохов Дима © (15.11.16 03:02) [43] > Скажи, вот ты стараешься избегать SEH как в моем примере?
У меня нет больших циклов, поэтому нечего оптимизировать.
-
> Какие же вы суперзадачи решаете, если на современных компьютерах > имеет проблемы с быстродействием. Завидую.
У меня с покером много вычислительных задач требуют время. Например, построить конечный автомат, который бы по пяти картам выдавал силу руки. По семи картам. Потом проверка того, что для всех раскладов перестановка карт не меняет силу руки. И т. д. и т. п.
-
> Внук © (11.11.16 13:01) [27] > Какие же вы суперзадачи решаете, если на современных компьютерах > имеет проблемы с быстродействием. Завидую.
Приходите к нам. Толковые разработчики нужны всегда.
Суть в том, что из текущих состояний дел в мире и ориентиров надо успевать обсчитывать несколько десятков тысяч операций в секунду, это будет соответствовать ожиданиям клиентов. А у нас каждая операция рассчитывается 1..2 мс, что, понятно, как минимум на порядок хуже. И при этом количество бизнес правил, которые надо проверять и учитывать, растёт. Такая вот фигня.
Понятно, что "менять архитектуру" и прочие красивые слова - прикольно, но это отдельная история.
Пока же меня лично беспокоит, что при написании нового кода то, что всё уже работает не быстро - вообще забывается. Т.е. абсолютно не учитывается почему-то.
-
> Толковые разработчики нужны всегда.
Не надо сманивать толковых разработчиков :)
-
Если учитывать, когда на компьютерах начали моделировать ядерные взрывы и решать другие сложные задачи, сравнить быстродействие тех и современных компьютеров, то говорить о нехватке быстродействия для бизнес-поделок, это из серии "слишком много кушать, в смысле - зажрались", нет? Понятно, что бизнес захочет получать всю в мире аналитику за секунду по нажатию кнопки. Только если говорить правду, выяснится, что не так уж это и надо, и не совсем уж за секунду, и вообще на перекуры больше времени уходит.
-
А есть например еще современные игрушки с фотореалистичной графикой. Там требования к ресурсам ого-го :)
-
> Внук © (16.11.16 10:51) [48] > Если учитывать, когда на компьютерах начали моделировать ядерные взрывы и решать другие сложные задачи, сравнить > быстродействие тех и современных компьютеров, то говорить о нехватке быстродействия для бизнес-поделок, это из серии > "слишком много кушать, в смысле - зажрались", нет?
На самом деле я вашу позицию полностью понимаю. Однако позволю себе разъяснить и другую позицию.
Имея возможности, бизнес желает обработать как можно больше операций, монетизируя каждую операцию. Так что скорость измеряется не всегда скоростью в микросекундах, но и capacity в смысле количества рассчитанных операций в единицу времени. Параметры отчасти взаимосвязанные (при ограничении на ресурсы), но не совсем буквально.
Ну и потом, как верно говорит начальник "главное в этой цепочке не быть самым медленным". Так что приходится не отставать от индустрии, и так по спирали каждый её участник, а что делать. Иначе деньги уйдут к другому. И тогда уже встанет вопрос "а что бы кушать мне", чего мне бы не хотелось, признаться. Когда-то и конвейеры были не нужны. Или нужны, но "а зачем?".
Если же вы в смысле пользы такого развития для человечества - то вопрос, конечно, мягко говоря, спорный, тут совершенно согласен. Однако ж и про расчет ядерных взрывов, как и сами взрывы - он тем более спорный, согласитесь.
-
> Внук © (16.11.16 10:51) [48]
> моделировать ядерные взрывы
моделирование моделированию рознь )
-
Про конкуренцию, это я понимаю.
Зато вспомнился случай из жизни, когда мы переводили нашу программу с MS-DOS на Windows, тогда только начала распространяться Win95, а компьютеры конечно были не самые свежие, но на которых DOS-овские программы вполне себе работали с хорошей скоростью Тогда нам несколько месяцев начальство выносило мозг на предмет того, почему запуск новой версии программы так ужасно медленно происходит по сравнению со старым досовским аналогом. Поскольку вопрос о том, чтобы НЕ переходит по Win, не стоял, оставалось только молча разводить руками и отводить душу в курилке :)
Мораль - хотите рюшечки, обеспечьте должное железо.
-
> запуск новой версии
Под запуском новой версии я имею в виду, конечно, время старта программы от момента щелканья по ярлыку до реакции на пользовательский ввод, а не время подготовки нового релиза.
-
> время старта программы ну так наверное все формы в автозагрузке, а там всякие конекшены в тру ))
-
> Внук © (16.11.16 15:51) [52] > Мораль - хотите рюшечки, обеспечьте должное железо.
В данном случае - увы, не поможет. В том смысле, что железо у клиентов в прямом смысле самое топовое, какое только можно купить в каждый конкретный момент на мировом рынке. Ну в рамках платформы, как она раньше называлась, IBM PC. (как называется сейчас, интересно?)
-
> ухты_х © (16.11.16 16:44) [54]
Это был, наверное, 1996 или 97-ой год, и программа была на C++ :)
-
|