Какую самую нелепую пессимизацию вы видели?

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

42 ответа

Никому не в обиду, но я просто оценил задание (java), в котором было это

import java.lang.*;

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

  • Коллекции карт или "словари"
    Они обычно используют какой-то вид хэш-кодирования, поэтому они будут иметь производительность O(1), но будут ломаться даже тогда, когда заполнены гораздо большим количеством элементов, чем обычно используется.

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

  • Уведомления и обработка событий как способ обеспечения согласованности данных
    Поскольку структура данных редко нормализуется, необходимо управлять несогласованностью, а уведомление является обычным методом, потому что он якобы решает проблему "немедленно". Однако между непосредственностью и эффективностью есть большая разница. Также "свойства", когда Get или Set, рекомендуется глубоко проникнуть в структуру данных, чтобы попытаться сохранить ее согласованность. Эти методы "короткого поводка" могут привести к большим потерям вычислений. Методы "длинного поводка", такие как периодическое циклическое переключение структуры данных для ее "восстановления", могут быть немного менее "немедленными", но гораздо более эффективными.

Примеры

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

"Эта часть не должна быть быстрой" (архивирование журналов) "Эта часть должна быть быстрой" (прием новых подключений)

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

Просто отвечая на простой вопрос: "Получу ли я что-нибудь от этой части кода очень быстро?" будет отличным ориентиром. Я имею в виду, что здравый смысл оптимизирует другие части проекта!

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

procedure sort(string[] values, string direction)
begin
  while not sorted do
  begin
    for every value in values
    begin
      if direction="Ascending" then
      begin
        ... swap values in ascending order
      end
      else if direction="Descending" then
      begin
        ... swap values in descending order
      end
    end;
  end;
end;

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

Некоторые мои коллеги, которые работали над проектом "оптимизации" существующих пакетов на стороне сервера (написанных на C++), "оптимизировали" до смерти класс журналирования (!), Используя специфический для win32 код и функции.

Возможно, узкое место было в logger.write(...), кто знает...

Еще один модный трюк производительности:)

if (!loadFromDb().isEmpty) {
    resultList = loadFromDb();
    // do something with results
}

За небольшую цену за дополнительный удар по БД вы экономите все это время, выполняя примерно 10 строк кода, что, вероятно, в любом случае ничего не даст для пустого списка. И такие вещи были разбросаны по всему коду:)

Один сотрудник должен был проверить доступ к странице для определенной роли - только "Администратор". Вот что она написала:

,

if( CurrentUser.CurrentRole == "Role1" || CurrentUser.CurrentRole == "Role2")  
{
// Access denied
} 
else
{
// Access granted
}

вместо

if( !CurrentUser.CurrentRole.equals("Admin") ) 
{
 // access denied
}  

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


Этот же сотрудник был также присоединен к производственной и архивной таблице для всех запросов.

Я собирался упомянуть StringBuilder для крошечных / нецикличных конкатов строк, но это было упомянуто.

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

Многие программисты не знают или не хотят знать SQL, поэтому они находят "хитрости", чтобы не использовать SQL, чтобы они могли получить данные в массив. Массивы делают некоторых людей счастливыми. (Мне нравятся как курсоры, так и массивы. Coke и Pepsi.) Я нашел эти два блока кода в коде нескольких объектно-ориентированных программистов, который жаловался на медлительность реляционных баз данных. (ответ не больше памяти или больше процессоров.)

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

Загрузите эти данные в arrayX (потому что массивы должны быть быстрее)

   Выберите uniqueid_col, col2, col3
     от super_big_tbl
 

(код псевдо)


Loop 
   arrayX.next_record
    if uniqueid_col = '829-39-3984'
      return col2
    end if
end loop
 

(Мой ответ внизу.)

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

   Выберите uniqueid_col, col2, col3
     от super_big_tbl
 сгруппировать по uniqueid_col, col2, col3
   имея uniqueid_col = '829-39-3984'

Правильный синтаксис должен быть

   Выберите uniqueid_col, col2, col3
     от super_big_tbl
    где uniqueid_col = '829-39-3984'
   

Приложение, которое использовало поле Integer для распределения по битам, к каким группам доступа к приложениям наши клиенты могут добавлять своих пользователей. Это означало, что в то время мы могли создать в общей сложности 32 группы, которые будут распределены между всеми 500+ клиентами.

А-а-а-а, но побитовое сравнение быстрее, чем равные, и да, быстрее, чем объединение, верно?

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

Ps

Я знаю, что вы думаете, это должно быть двоичная строка, верно?:)

У меня есть преднамеренный... Я однажды реализовал сортировку с помощью обратного отслеживания... просто как подтверждение концепции;)) Излишне говорить, что его производительность была ужасающей.

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

Другие вопросы по тегам