Конференция "Прочее" » "Преждевременная оптимизация — корень всех зол"
 
  • KSergey © (10.11.16 09:54) [0]
    Какой идиот это написал? (фамилию я знаю)

    Или спрошу иначе: почему эта фраза трактуется как "оптимизировать не нужно", "думать про то, как твой код будет работать в смысле скорости - не нужно"?

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

    В итоге когда выясняется, что "всё работает медленно" - не удаётся даже заоптимизировать код, потому как он равномерно выполняется, каждая вложенная функция как бы небольшую часть времени занимает.
  • Игорь Шевченко © (10.11.16 10:16) [1]
  • KSergey © (10.11.16 10:43) [2]
    Это я читал.

    Но что я не понимаю?
  • DayGaykin © (10.11.16 11:31) [3]
    Сейчас модно делать так:
    1. Сначала пишешь тест.
    2. Потом реализацию проходящую этот тест (как угодно: хоть с goto).
    3. Когда тест пройдет, проводишь рефакторинг и делаешь оптимизации.
  • Внук © (10.11.16 12:22) [4]
    Наверно, здесь ключевое слово - "преждевременная"
  • Игорь Шевченко © (10.11.16 12:32) [5]
    KSergey ©   (10.11.16 10:43) [2]

    Гугль:
    "практика программирования первый принцип оптимизации - по возможности избегать ее"

    Оптимизацию следует начинать с поиска узких мест при помощи профилирования программы. Оптимизировать при проектировании или при написании кода стоит ровно в одном случае, когда опыт подсказывает  быстрые решения (например, не использовать TMemo для поиска строк в файле).
  • KSergey © (10.11.16 12:54) [6]
    Что в итоге.
    Имеем софт, который работает медленно (в смысле требуется на порядок быстрее).
    Профилирование показывает, что нет участков вода, которые можно оптимизировать в том смысле, что все ровным слоем размазано, нет явных мест, занимающих 90% времени.

    Всё переписать - ресурсов нет.
    Всё после переписывания перетестировать - тем более нет ресурсов.
    новый код пишется по тому же принципу.

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

    Что я не понимаю? где я ошибаюсь?
  • Внук © (10.11.16 13:02) [7]
    На мой взгляд, ты ошибаешься в том, что "любые указания на то, что вот в этом месте нового кода можно вот это сделать хоть как-то оптимальнее" спасут ситуацию в этом случае. Оно как было размазано ровным слоем, так и останется, за исключением того места, на которое ты указал, оптимизация которого не сыграет никакой роли, раз уж оно ровным слоем.
  • Игорь Шевченко © (10.11.16 13:45) [8]
    Надо менять всю систему
  • L_G © (10.11.16 15:23) [9]
    Кнут написал это для умных программистов, которые понимают, что оптимизация - это замена краткого и понятного кода на более быстрый, но и более длинный и/или хуже читаемый. Этого преждевременного ухудшения читаемости (усложнения) он и советует избегать. Он не взял в расчет, что ленящийся думать (но не печатать) программист может написать вместо краткого кода более длинный, но тупой, да при этом еще и более медленный. Его замена на более понятный и согласованный с принципом DRY код - рефакторинг, оптимизацией даже не являющийся. Понятность и DRY - прежде скорости, но уж если они заодно - сам бог велел...
  • Юрий Зотов © (10.11.16 18:39) [10]
    Надо для начала определиться, что такое "быстро" и что такое "медленно".

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

    Это быстро или медленно?

    С практической точки зрения - нормально. Юзер эти 250 мс даже и не заметит.

    Надо ли оптимизировать эту кучу операций?

    Видимо, оптимизация в данном случае смысла не имеет. Поэтому, если мы провели оптимизацию еще на этапе первоначального написания кода, то мы просто зря потратили время.
  • Pavia © (10.11.16 19:29) [11]
    Всё очень просто. Есть структуры данных, их немного. Эта единственная область теоретически обоснованная. И в ней всё понятно что и когда выбирать. Вставка, удаление, поиск. 3^3 всего 27 их должен знать каждый. Их надо применять сразу. Остальное можно оставить напотом. Так как для низ нет критерия быстро или медленно. Быстро и медленно вводится только от параметра и то только в пределе. О-большое или теэта-большая. Поэтому о скорости мы всегда говорим относительно алгоритмов. А как известно структуры связаны с алгоритмами.
  • Pavia © (10.11.16 19:33) [12]
    Есть госты по эргономике если операция длится дольше 0.1 секунды то должна быть индикация или сигнализация.
  • kilkennycat © (10.11.16 20:39) [13]
    а под оптимизацией ваще-то не только скорость подразумевается, у меня в компиле ваще можно регулировать, в какую сторону приоритетить - скорости или ресурсов.

    Кнут енто говорил лет тыщу назад и во-первых, он всего лишь человек, и во-вторых каждый пишет как хочет.

    Лично я вовсю преждевременно оптимизирую. И как-то менее глюкаво выходит в итоге.
  • Тимохов Дима © (11.11.16 00:47) [14]
    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));
         // Понимаю, что
         //    raise Exception.CreateFmt('wrong %d', [J]);
         // не давало бы SEH, но это же пример!
    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;

  • Дмитрий Белькевич © (11.11.16 01:03) [15]
    Оптимизация оптимизации рознь. Например - у нас есть довольно сложный алгоритм, который вначале разрабатывался исходя из стабильности и читабельности, потом переписали под максимальное быстродействие - с целыми числами и почти 100% использованием разрядной сетки вместо дробных и так всякими заморочками. Если бы делали оптимизацию сразу - то это очень сильно бы усложнило задачу.
    С другой стороны - если есть обычный код, без особенных заморочек, то почему бы сразу не применить известные методы?

    Всё есть яд и всё - лекарство.
  • Германн © (11.11.16 02:41) [16]

    > Всё есть яд и всё - лекарство.
    >

    Соглашусь.
    А подобные советы Кнута или кого ещё нельзя выдергивать из контекста.
  • KSergey © (11.11.16 09:16) [17]
    > Юрий Зотов ©   (10.11.16 18:39) [10]
    > Надо для начала определиться, что такое "быстро" и что такое "медленно".

    Уважаемый ЮЗ!
    Это совсем другая тема и нет смысла её сюда приплетать.
    Как я изначально указал, есть софт, скоростью работы которого уже недовольны (т.е. требуется на порядок быстрее объективно, и это не пользовательский интерфейс), но софт развивается функционально, естественным образом замедляясь ввиду добавления нового кода.

    Так что уже определились: софт работает недопустимо медленно.
  • iop © (11.11.16 10:32) [18]
    "Преждевременная оптимизация — корень всех зол"

    по сравнению с преждевременной эякуляцией это просто пустяк.
  • Юрий Зотов © (11.11.16 10:38) [19]
    > KSergey ©   (11.11.16 09:16) [17]

    > Это совсем другая тема и нет смысла её сюда приплетать.
    > Как я изначально указал, есть софт, скоростью работы
    > которого уже недовольны


    Перечитайте [0]. Вот как раз ИЗНАЧАЛЬНО (т.е. в сабже) Вы никакого конкретного софта НЕ указали, а только процитировали известную фразу и высказались по ее поводу. Причем высказались обобщенно, не указав, опять же, никакого конкретного случая.

    Соответственно, обсуждение в ветке пошло в заданном Вами же плане - вообще, а не по Вашей проблеме конкретно. Поэтому претензии на этот счет Вам следует предъявлять самому себе.

    По поводу [6] совет такой: гуру либо прав, либо неправ. Дождитесь результата.

    По поводу тормозов, которые "размазаны тонким слоем". Когда-то пришлось мне оптимизировать код, в котором тормоза были именно "размазаны тонким слоем". Обращало на себя внимание то, что во многих местах длинными цепочками вызывалась куча геттеров. Примерно так:
    getA.getB.getC...getX.getY.getZ


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

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

    Что и сделал, потратив совсем немного времени. Результат почти  ошеломил - скорость тут же выросла примерно в 50 раз и была признана достаточной.

    Это я к тому, что "тормоза тонким слоем" могут получиться, в том числе, из-за того, что во многих местах вызывается инвариантный код (любой, не только геттеры). Сам по себе этот код может быть и не особо медленным, но в сумме дает те самые "размазанные тормоза". Не Ваш ли это случай?
 
Конференция "Прочее" » "Преждевременная оптимизация — корень всех зол"
Есть новые Нет новых   [134431   +11][b:0][p:0.002]