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

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

«Пессимизация» - отличное слово.

mqp 26.03.2009 20:31

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

mmcdole 26.03.2009 20:44

Файл жаргона: catb.org/jargon/html/P/pessimal.html, catb.org/jargon/html/P/pessimizing-compiler.html

Beni Cherniavsky-Paskin 29.04.2014 01:53
За пределами сигналов Angular: Сигналы и пользовательские стратегии рендеринга
За пределами сигналов Angular: Сигналы и пользовательские стратегии рендеринга
TL;DR: Angular Signals может облегчить отслеживание всех выражений в представлении (Component или EmbeddedView) и планирование пользовательских...
Sniper-CSS, избегайте неиспользуемых стилей
Sniper-CSS, избегайте неиспользуемых стилей
Это краткое руководство, в котором я хочу поделиться тем, как я перешел от 212 кБ CSS к 32,1 кБ (сокращение кода на 84,91%), по-прежнему используя...
146
3
16 477
42
Перейти к ответу Данный вопрос помечен как решенный

Ответы 42

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

String msg = "Count = " + count + " of " + total + ".";

в

StringBuffer sb = new StringBuffer("Count = ");
sb.append(count);
sb.append(" of ");
sb.append(total);
sb.append(".");
String msg = sb.toString();

Раньше было довольно распространенной практикой использовать эту технику в цикле, потому что это было заметно быстрее. Дело в том, что StringBuffer синхронизирован, поэтому на самом деле возникают дополнительные накладные расходы, если вы объединяете только несколько строк. (Не говоря уже о том, что разница в этой шкале совершенно тривиальна.) Два других момента об этой практике:

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

Во-первых: если вы не используете Java 5, у вас нет StringBuilder. Во-вторых: нельзя рассчитывать на оптимизацию JVM. Принимая во внимание первый и второй оператор, первый оператор СОЗДАЕТ 5 ОБЪЕКТОВ, а второй создает один, а возможно, и два объекта.

MetroidFan2002 23.11.2008 09:39

Второй момент: компиляторы могут использовать StringBuffer за кулисами в любом случае: java.sun.com/docs/books/jls/third_edition/html/expressions.h‌ tml

MetroidFan2002 23.11.2008 09:43

Во-первых: почему бы вам не использовать хотя бы Java 5? Во-вторых: да, можно. Как получилось, что в первом примере можно сосчитать до 5, а во втором - нет? Он использует те же строковые литералы, что и первый. Напишите читаемый код и позвольте компилятору решить, когда использовать StringBuffer за кулисами.

Bill the Lizard 23.11.2008 16:06

Второй использует один StringBuffer, а затем создает String. Это два объекта. Первый создает экземпляр StringBuffer для каждой объединенной строки. Во-вторых, политика рабочего пространства иногда препятствует использованию Java 5. Например, при развертывании на Websphere 6.0 вы ограничены Java 1.4.

MetroidFan2002 31.12.2008 21:18

Я видел то же самое в .NET (ТОЛЬКО отличие - это имя класса StringBuffer -> StringBuilder)

Andrei Rînea 26.03.2009 13:16

@ MetroidFan2002: Строковые литералы во втором примере тоже являются объектами. Как я уже сказал в ответе, в этом масштабе различия тривиальны.

Bill the Lizard 26.03.2009 14:53

@Bill - во втором примере нет другого StringBuffer для каждой строки. Первый пример может быть (за кулисами) эквивалентом String msg = new StringBuffer ("Count = ") .append (new StringBuffer (count) .append (...) - new StringBuffers для каждой строки. Во втором примере нет не делай этого.

MetroidFan2002 26.03.2009 20:37

@ MetroidFan2002: Раздел 15.18.1.2 из вашей ссылки выше: Реализация может выбрать выполнение преобразования и конкатенации за один шаг, чтобы избежать создания, а затем отбрасывания промежуточного объекта String. (продолжение ...)

Bill the Lizard 26.03.2009 21:16

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

Bill the Lizard 26.03.2009 21:17

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

Bill the Lizard 26.03.2009 21:18

Первый метод занимает одну строку и не вызывает вызова. Второй метод занимает 6 строк, 5 вызовов методов и один новый вызов. Прежде всего, читаемость!

Eric 26.03.2009 22:19

@Eric: String msg = "Count = " + count + "of" + total + "."; часто компилируется в Java в String msg = new StringBuffer (). append ("Count"). append (count) .append ("of") .append (total) .append ("."). toString (); ... именно это и делает второй пример.

Grant Wagner 27.03.2009 00:35

@ Эрик: Подтверждено. javac 1.6.0_12 декомпилируется в String s = (new StringBuilder ()). append ("Count = ") .append (i) .append ("of") .append (j) .append ("."). toString ( ); - ШЕСТЬ вызовов методов и один новый вызов. Не говорить, что явный SB лучше, но + конкатенация не удаляет вызовы методов, а просто скрывает их.

Grant Wagner 27.03.2009 00:54

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

ypnos 27.03.2009 19:08

+1 Я вижу даже лучше. Использование StringBuilder для объединения группы строк константы в VB.NET вместо объединения их с помощью &. Последний излучает только одну большую строковую константу в MSIL, первый создает довольно тяжелый объект и вызывает его методы. Для каждого запроса.

Tomek Szpakowicz 05.04.2009 00:57

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

Andrei Rînea 27.04.2009 02:18

Я видел людей, использующих alphadrive-7 для полной инкубации CHX-LT. Это необычная практика. Более распространенной практикой является инициализация трансформатора ZT, чтобы уменьшить буферизацию (из-за большей устойчивости к сетевой перегрузке) и создать байтографию в стиле Java.

Совершенно пессимистично!

возможно они пытались усилить конденсатор потока

Mikeage 26.03.2009 13:55

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

Matt Rogish 26.03.2009 23:31

+1 потому что мой монитор все равно нуждался в чистке ;-)

RBerteig 27.03.2009 00:00

Черт!! А как насчет электромагнитно-кросс-генетического эффекта. Думаю, это тоже нужно учитывать. Или субъект может превратиться в зомби.

Suraj Chandran 04.02.2010 06:24

Три слова: «Хромированные подшипники глушителя».

Allbite 28.05.2010 01:47

Базы данных - это игровая площадка для пессимизации.

Избранное включает:

  • Разделите таблицу на несколько частей (по диапазону дат, алфавиту и т. д.), Потому что она «слишком велика».
  • Создайте архивную таблицу для исключенных записей, но продолжайте ОБЪЕДИНЕНИЕ ее с производственной таблицей.
  • Дублируйте целые базы данных по (подразделению / заказчику / продукту / т. Д.)
  • Не добавляйте столбцы в индекс, потому что он становится слишком большим.
  • Создавайте множество сводных таблиц, потому что пересчет необработанных данных выполняется слишком медленно.
  • Создавайте столбцы с подполями для экономии места.
  • Денормализовать в поля как массив.

Это не в моей голове.

О том, чтобы сопротивляться необходимости индексировать, просто больно думать.

Bill the Lizard 23.11.2008 05:58

Да, я знаю кого-то, кто работает в крупной нефтяной компании США, где почти все их таблицы имеют связанную архивную таблицу, и большинство запросов выбирают из представлений, которые объединяют пары таблиц. Производительность такая, как и следовало ожидать!

Tony Andrews 26.03.2009 16:32

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

Cruachan 26.03.2009 22:39

Добавляю: разбить базу данных на несколько разных баз (клиенты a-c, клиенты d-f и т. д.)

Gabriele D'Antona 01.05.2009 12:13

Не могли бы вы подробнее рассказать о «Денормализовать в поля как массив»? Что вы здесь имеете в виду?

Bart van Heukelom 27.09.2011 13:10

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

dkretz 27.09.2011 22:56

@le dorfier теперь мне приходит в голову, что обычно идея поля как массива реализуется без добавления столбцов. Они просто кодируют массив в существующий столбец, создавая огромные постоянно растущие строки XML и сохраняя их в столбце. Вздох. Год спустя они инвестируют в аппаратный модуль обработки XML. Это никогда не закончится.

TheBlastOne 17.06.2013 19:14

Это может быть на более высоком уровне, чем то, что вам нужно, но исправление этого (если вам разрешено) также связано с более высоким уровнем боли:

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

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

Kibbee 23.11.2008 05:58

Я никогда не думал, что это всегда плохая идея. Я сомневаюсь, что ORM / DAL - это основная бизнес-функция, если вы не скажете Франса Баумы или ему подобных. Крайне неэффективно писать собственный эквивалент - случай заново изобрести (квадратное) колесо, обычно из-за синдрома NIH.

Gordon Hartley 24.11.2008 03:25

@Kibbee - согласен. Лучше бросить свой собственный и понять это, чем использовать сторонние зависимости. Когда он сломается (а он сломается), по крайней мере, вы сможете его исправить. В прошлом я обнаруживал ошибки в Hibernate и Apache Commons, которые полностью убивали производительность нашего приложения.

CodingWithSpike 06.02.2009 23:31

Дело в том, что приличную ORM очень сложно написать. Конечно, моделировать записи как объект с помощью удобных методов вставки / обновления легко, но как только вы попытаетесь предоставить API, который поддерживает объединения и создает эффективный SQL, вы попадаете в мир боли.

SpoonMeiser 26.03.2009 14:09

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

staticsan 14.04.2009 08:45

На самом деле, с учетом некоторых из вышеперечисленных комментариев, некоторые более перспективные: еще одна пессимизация - это попытаться заставить ORM делать абсолютно все. Часто это полезно в 95% + случаев. Для этих последних 5% гораздо проще отказаться от созданного вручную кода сохраняемости / прямых вызовов хранимых процедур и т. д. Для повышения производительности, простоты или того и другого.

Gordon Hartley 30.11.2010 09:09

Однажды я работал над приложением, полным такого кода:

 1 tuple *FindTuple( DataSet *set, int target ) {
 2     tuple *found = null;
 3     tuple *curr = GetFirstTupleOfSet(set);
 4     while (curr) {
 5         if (curr->id == target)
 6             found = curr;
 7         curr = GetNextTuple(curr);
 8     }
 9     return found;
10 }

Просто удалите found, верните null в конце и измените шестую строку на:

            return curr;

Увеличена производительность приложения вдвое.

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

flolo 23.11.2008 12:26

Место, в котором был этот код, также имело правило «один возврат в конце».

Dour High Arch 24.11.2008 08:18

Здесь return curr ведет к заметно иному поведению. Когда вы возвращаете curr, вы получаете ПЕРВОЕ совпадение, а вставленный вами код возвращает ПОСЛЕДНЕЕ совпадение.

SoapBox 28.11.2008 04:08

@SoapBox: Вы правы. @Dour High Arch: повышение производительности не имело ничего общего с правилом единственного возврата, как сказал Флоло, изменение условия цикла на (curr &&! Found) будет иметь тот же эффект. ПЕРЕЙТИ к выходу из процесса ужасен и сводит на нет цель единственного возврата.

Akusete 28.11.2008 04:23

Использование break; было бы лучше, чем добавлять дополнительное условие к while ().

Adam Pierce 28.11.2008 05:58

Хорошие комментарии всем. В этом случае предполагалось, что будет только один кортеж с каждым идентификатором.

Dour High Arch 29.11.2008 06:09

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

jussij 19.02.2009 07:44

В старом коде действительно есть ошибка производительности, связанная с добавлением "break;" исправил бы красиво.

ksuralta 26.03.2009 12:21

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

Chris R 31.03.2009 07:57

@Chris R: Использование GOTO создает дополнительную нагрузку на программиста по обслуживанию - они должны определить, что это на самом деле просто замаскированный перерыв. Кроме того, возможно, что goto, который сегодня действует как break, пропустит некоторый код, добавленный сразу после цикла завтра. Я говорю, будь проще

Tom Leys 05.05.2009 08:35

Но это же не «пессимизация», не так ли? Это просто ожидаемая оптимизация.

Tim Long 12.05.2009 23:14

Ваша версия возвращает первое совпадение, а исходная функция возвращает последнее совпадение.

Adrian McCarthy 27.05.2009 03:09

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

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

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

  • Чтение одного и того же ключа реестра тысячи (или десятки тысяч) раз во время запуска программы.
  • Загрузка одной и той же DLL сотни или тысячи раз
  • Пустая трата мегабайт памяти из-за ненужного сохранения полных путей к файлам
  • Не организовывать структуры данных, чтобы они занимали намного больше памяти, чем им нужно.
  • Определение размера всех строк, в которых хранятся имена файлов или пути, до MAX_PATH
  • Беспричинный опрос для вещей, у которых есть события, обратные вызовы или другие механизмы уведомления

Я думаю, что лучше всего будет следующее утверждение: «Оптимизация без измерения и понимания - это вообще не оптимизация - это просто случайное изменение».

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

Странно, что за это проголосовали отрицательно. Во всяком случае, информативный пост.

Joseph Ferris 23.11.2008 06:27

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

Bill the Lizard 23.11.2008 06:52

Re: упаковка структур данных ... Я знал парня, который всегда ставил #pragma pack 1 во главе каждого исходного файла. В конечном итоге он укусил его на какой-то платформе, которая требовала выравнивания значений DWORD, когда он передавал указатель на член структуры DWORD и вместо этого получал случайные значения.

Hasturkun 23.11.2008 15:08

@Foredecker: отлично. Слишком многие люди забывают контекст, который ставит эту цитату категорически против микро-оптимизации. Анализ проблемы для выбора правильного алгоритма перед ее реализацией не преждевременно, но слишком часто эта цитата выдвигается, чтобы оправдать самое ленивое и самое неэффективное решение.

Shog9 23.11.2008 19:30

Привет, Билл-ящерица :) Я полностью понимаю, о чем вы - это то, что имел в виду Кнут. Но сама фраза НАМНОГО переоценена.

Foredecker 24.11.2008 01:21

Опечатка: "опрос" вместо "опрос" извините, ничего не могу с собой поделать :) Все равно +1

MarkJ 28.02.2009 22:40

+1 Один пример из какого-то кода, над которым мне нужно работать - чтение одного и того же значения из базы данных 100 раз за ОДНУ операцию. Я постепенно работаю над его рефакторингом, но это сложно.

Mark Pim 26.03.2009 12:14

@Foredecker: Я понимаю, что вы имеете в виду, говоря о злоупотреблении этой фразой. Если вы говорите это вслух, это, вероятно, знак того, что вам нужно измерить свой код. :)

Bill the Lizard 26.03.2009 19:16

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

Mark Rogers 26.03.2009 20:40

-1: Есть разница между «оптимизацией» и правильным дизайном. Для тех, кто не может сказать, хорошее практическое правило состоит в том, что «оптимизация» делает код более сложным для чтения, но более быстрым или эффективным. Лучший дизайн сделает код более простым для чтения (или, по крайней мере, не хуже) и более эффективным.

T.E.D. 26.03.2009 23:43

Я полностью согласен. Я сообщил об ошибке в Microsoft, когда библиотека .NET выполняла некоторое взаимодействие и вызывала LoadLibrary сотни и сотни раз, когда ей требовалось всего около 30 вызовов. Я написал аналогичный код, который занимал секунды, а не минуты. MS не использовала это исправление. :)

BobbyShaftoe 27.03.2009 09:28

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

Foredecker 27.03.2009 21:39

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

dkretz 28.03.2009 00:41

Этим злоупотребляют, и мне тоже надоела эта фраза! Я как раз думал об этом вчера!

JAL 29.03.2009 10:54

«Тратить мегабайты памяти на напрасное сохранение полных путей к файлам» - это так забавно в этом контексте. Хотя, полагаю, непреднамеренно?

Dun3 01.04.2009 20:07

Я вижу, что это использовалось для постоянного оправдания полной траты ЦП.

doug65536 15.02.2014 00:38

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

user207421 01.02.2016 02:53

Давай, ребята. Это «преждевременная оптимизация Любовь - корень всех зол».

Don Hatch 04.08.2017 10:23

Однажды я видел базу данных MSSQL, в которой использовалась «Корневая» таблица. В корневой таблице было четыре столбца: GUID (uniqueidentifier), ID (int), LastModDate (datetime) и CreateDate (datetime). Все таблицы в базе данных имеют внешний ключ к корневой таблице. Всякий раз, когда новая строка создавалась в таблице Любые в базе данных, вам приходилось использовать пару хранимых процедур для вставки записи в корневую таблицу, прежде чем вы могли добраться до фактической таблицы, о которой вы заботились (вместо того, чтобы база данных выполняла работу для вы с несколькими триггерами простые триггеры).

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

Разработчик, выбравший этот путь, защищал его, полагая, что это сэкономило массу места, потому что мы не использовали Guids в самих таблицах (но ... разве GUID не создается в корневой таблице для каждой создаваемой нами строки?) , как-то улучшили производительность и упростили аудит изменений в базе данных.

Да, и диаграмма базы данных выглядела как паук-мутант из ада.

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

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

С другой стороны, наши разработчики программного обеспечения решили, что распакованные данные должны быть отформатированы в хорошо читаемый XML-документ и сохранены в нашей базе данных как таковые (в отличие от того, чтобы каждое поле сохранялось в соответствующем столбце). Их идея заключалась в том, что «будущее за XML», «дешевое дисковое пространство» и «дешевый процессор», поэтому не было необходимости что-либо оптимизировать. В результате наши 16-байтовые пакеты были преобразованы в документы размером 2 КБ, хранящиеся в одном столбце, и даже для простых запросов нам приходилось загружать в память мегабайты XML-документов! Мы получали более 50 пакетов в секунду, так что вы можете себе представить, насколько ужасной стала производительность (кстати, компания обанкротилась).

Итак, опять же, не существует абсолютного правила. Да, иногда слишком ранняя оптимизация - это ошибка. Но иногда девиз «ЦП / дисковое пространство / память дешево» является настоящим корнем всех зол.

Я согласен, что «процессор / дисковое пространство / память дешевы» - это настоящий корень всех зол. +1

ksuralta 26.03.2009 12:19

Я тоже слышал эту чушь XML. Еще одна затонувшая рота.

n8wrl 26.03.2009 23:21

@ksuralta: «ЦП / дисковое пространство / память дешевы» - удобный предлог, чтобы не думать. Избегание мыслей - это мнимый корень всех зол.

Piskvor left the building 28.03.2009 15:33

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

Tanz87 15.01.2017 20:31

Моему бывшему коллеге (на самом деле s.o.a.b.) было поручено создать новый модуль для нашей Java ERP, который должен был собирать и анализировать данные о клиентах (розничная торговля). Он решил разделить КАЖДОЕ поле календаря / даты и времени на компоненты (секунды, минуты, часы, день, месяц, год, день недели, биметр, триместр (!)), Потому что «как еще я мог бы запросить« каждый понедельник »?»

Это не преждевременная оптимизация, он подумал, что это нужно сделать для правильности.

Pyrolistical 28.11.2008 04:24

Конечно, он мысль, ему это было нужно, но поскольку в большинстве СУБД есть какая-то функция DAYOFWEEK (timestamp), делать этот беспорядок заранее, на мой взгляд, достаточно преждевременно :)

Joril 02.12.2008 15:40

Я бы не стал использовать его для OLTP, но если вы «анализируете данные клиентов», то на самом деле это очень гибкий способ проектирования хранилища данных (при условии, что дата и время разделены на разные измерения). Вы действительно хотите вызвать DAYOFWEEK () для миллионов строк данных или просто выполнить поиск по индексу для целочисленного поля?

Tim Medora 16.12.2010 19:56

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

Joril 16.12.2010 20:19

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

import java.lang.*;

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

Bryan Oakley 26.03.2009 14:05

О, я не возражал против ученика, но мне было интересно, что заставит ученика включить строку (не похоже, чтобы она не компилировалась раньше)

Overflown 26.03.2009 14:28

Java достаточно умен, чтобы нет импортировать то, что ему не нужно, когда вы используете blob (*) для импорта. Это не так плохо, как ненужные #includes в C и C++. Тем не менее, тот факт, что студент чувствует необходимость импорта из java.lang, вызывает беспокойство. :)

Bill the Lizard 26.03.2009 15:07

Собираюсь ли я быть единственным, кто заметит иронию того, что учитель вызывает WTF из-за кода ученика, который он / она отвечает за обучение правильному программированию?

JohnFx 26.03.2009 18:54

@JohnFx: невероятно забавно. Однако помните, что плохой учитель может иметь плохого ученика.

Dinah 26.03.2009 18:59

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

cygil 26.03.2009 21:04

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

Overflown 27.03.2009 00:49

@JohnFX: Оценщик и учитель - не всегда одно и то же.

Eddie 06.07.2010 23:51

Разве это не обязательно в C#, чтобы импортировать базовый языковой материал?

Dan Rosenstark 01.01.2011 06:07

Это звучит как хорошая экономия времени для java-студентов, которые они могут использовать в шаблоне, когда они не знают наверняка, что они будут использовать ... конечно, окончательная представленная версия должна быть исправлена, но тем временем это PITA для постоянно добавлять / удалять импорт, потому что это отнимает много времени и отвлекает вас от текущей задачи. Как программист на C, Google foobar был интересным способом изучения Java, который требовал тестирования нескольких способов выполнения одной и той же задачи в соответствии с требованиями времени - каждый из которых требовал разного набора операций импорта. Я потратил почти столько же времени на поиск импорта, сколько на кодирование.

technosaurus 18.05.2017 18:44

Использование регулярного выражения для разделения строки, когда достаточно простого string.split

НО в Java String.Split использует регулярное выражение!

Frank Krueger 30.03.2009 02:16

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

Andrei Rînea 27.04.2009 02:19

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

David Crawshaw 03.10.2009 02:36

@ Дэвид Кроушоу: Поиск возможностей микрооптимизации тратит человеческое время; bud, когда код пишу, используйте наименее сложное достаточное решение.

Piskvor left the building 25.08.2010 15:27

-1: Если вы привыкли к регулярным выражениям, вполне естественно написать это вместо того, чтобы привыкать к внутренним строковым манипуляторам языка 1001.

KillianDS 23.08.2011 21:09

Господи, думаю, я их всех видел. Чаще всего это попытка исправить проблемы с производительностью кем-то, кто слишком ленив, чтобы найти их ПРИЧИНУ этих проблем с производительностью или даже выяснить, действительно ли существует проблема с производительностью. Во многих из этих случаев я задаюсь вопросом, не является ли это просто случаем, когда человек хочет опробовать определенную технологию и отчаянно ищет гвоздь, который подошел бы их новому блестящему молотку.

Вот недавний пример:

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

Мне: Почему вы об этом думаете? Какую проблему вы пытаетесь решить?

Ему: Таблица X слишком велика, мы разбиваем ее по соображениям производительности.

Мне: С чего вы взяли, что он слишком широкий?

Ему: Консультант сказал, что слишком много столбцов для одной таблицы.

Мне: А это влияет на производительность?

Ему: Да, пользователи сообщали о периодических замедлениях работы модуля XYZ приложения.

Мне: Как узнать, что ширина таблицы является источником проблемы?

Ему: Это таблица ключей, используемая модулем XYZ, и она похожа на 200 столбцов. Это должно быть проблема.

Я (объясняя): Но модуль XYZ, в частности, использует большинство столбцов в этой таблице, а используемые им столбцы непредсказуемы, поскольку пользователь настраивает приложение для отображения данных, которые он хочет отобразить из этой таблицы. Вероятно, что в 95% случаев мы все равно объединим все таблицы вместе, что снизит производительность повредить.

Ему: Консультант сказал, что он слишком широк и нам нужно его изменить.

Мне: Кто этот консультант? Я не знал, что мы наняли консультанта, и они вообще не разговаривали с командой разработчиков.

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

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

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

  1. Отсутствуют индексы по нескольким ключам столбцы.
  2. Несколько аналитиков-мошенников, которые периодически блокировка ключевых таблиц (в том числе "слишком широкий") запросив производственная база данных напрямую с MSAccess.

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

Aaag MS Доступ к продукту. Мы написали процедуру, позволяющую разрывать все соединения доступа каждые несколько минут, чтобы наконец получить сообщение о том, что это плохо.

Nat 26.03.2009 23:37

У нас была аналогичная работа, но она вышла из употребления. Честно говоря, Access - не проблема, он просто упрощает для новичков создание / выполнение неэффективных запросов.

JohnFx 27.03.2009 00:19

В нашей компании у нас есть зависимость от устаревших специальных подключений Access к производственной БД. Нет ничего лучше, чем несколько случайных операторов SQL, которые забыли предложение WHERE и заблокировали основные таблицы!

HardCode 28.03.2009 08:09

"Я слышал, у лилового больше всего RAM"

Piskvor left the building 28.03.2009 15:37

Это могло бы быть и хуже. Редактор запросов Excel блокирует всю базу данных при ее использовании. Когда я не знал об этом, я оставлял один экземпляр открытым на большую часть дня, пока работал над чем-то другим. Хуже всего то, что MS SQL Server не сообщил правильное имя пользователя / машину, которая производила блокировку. Через несколько часов я понял, что причиной блокировки был я, потому что заблокированные таблицы были частью представления, которое я запрашивал, и сначала проверил все остальное.

Esteban Küber 17.01.2010 08:13

Проверка перед КАЖДОЙ операцией javascript, существует ли объект, с которым вы работаете.

if (myObj) { //or its evil cousin, if (myObj != null) {
    label.text = myObj.value; 
    // we know label exists because it has already been 
    // checked in a big if block somewhere at the top
}

Моя проблема с этим типом кода в том, что никого не волнует, а что, если его не существует? Просто ничего не делать? Не оставляете отзыв пользователю?

Я согласен, что ошибки Object expected меня раздражают, но это не лучшее решение для этого.

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

simon 31.03.2009 17:35

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

Пессимизм заключается в том, что разработчик думал, что повторные вызовы веб-службы будут слишком медленными, чтобы делать повторяющиеся запросы SQL. И что он сделал? Событие запуска приложения считывает всю базу данных и преобразует все это в объекты в памяти, которые хранятся на неопределенный срок, пока пул приложений не будет перезапущен. Этот код был настолько медленным, что на его загрузку ушло менее 2000 сотрудников. Если вы непреднамеренно перезапустили пул приложений в течение дня, это может занять 30 минут или больше, потому что каждый запрос веб-службы будет запускать несколько одновременных перезагрузок. По этой причине новые сотрудники не будут отображаться в базе данных в первый день создания их учетной записи и, следовательно, не смогут получить доступ к большинству внутренних приложений в первые несколько дней своей работы.

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

Лучшее управление - «Нет, давайте не будем тратить 80 часов программиста на исправление этого приложения, это слишком дорого. Давайте просто сохраним его, чтобы его ошибки могли истощить 200+ пользовательских часов в месяц, плюс 10 часов программиста в месяц на 'техническое обслуживание'." АААААААААААА !!!

Piskvor left the building 28.03.2009 15:45

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

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

Rob 26.03.2009 22:22

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

chris 27.03.2009 03:53

+1, Крис: Я работаю над термоусадочной пленкой и веб-приложениями с 1998 года, и мне ни разу ни разу не понадобилось менять продукты СУБД (за исключением поддержки Sybase ASE и SQL Server, что довольно просто делать)

Matt Rogish 27.03.2009 17:42

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

mfx 27.03.2009 19:37

Я уверен, что это случается, но достаточно редко вы становитесь идиотом, если проектируете свою архитектуру с учетом этой возможности.

chris 27.03.2009 20:48

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

Cory R. King 29.03.2009 10:37

Правда, ребята? А как насчет продуктов для перепродажи, таких как FogBugz, который поддерживает SQL Server, Access и MySql? Делает ли это Джоэла «идиотом» или «астронавтом-архитектором»?

harpo 30.03.2009 23:33

В самом деле, я работал над многочисленными проектами, которые должны были (или решили) изменить dbs. Однако у нас не было глупых правил, позволяющих избегать внешних ключей, поскольку мы предполагали, что любая используемая нами база данных будет иметь хотя бы некоторую разумность в качестве СУБД. И портирование триггеров производилось при необходимости (хотя и избегалось).

jsight 31.03.2009 01:33

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

chris 31.03.2009 03:35

@All: Независимость от БД может стоить вам, да, но наш продукт работает в средах, где поставщик БД выбирается на основе ставок, и нам в основном приходится подыгрывать. Некоторые разработчики не могут позволить себе роскошь вертикально интегрированного программного стека и вынуждены довольствоваться этим.

Chris R 31.03.2009 08:00

Почему бы просто не использовать MySQL, MariaDB или PostgreSQL? Все бесплатно, покупка не требуется.

Demi 27.05.2015 19:07

@Demetri: очевидно, вы никогда не работали в правительственной среде, где платная поддержка коммерческого продукта в основном является обязательным требованием. Выбор продукта без того, чтобы кого-то винить, ограничивает карьеру в бюрократическом мышлении.

chris 27.05.2015 20:22

Я понимаю, в чем проблема - вас обвинят, если винить некую компанию. Если вы использовали Postgres, вы все равно могли бы распространять СУБД вместе с продуктом (Postgres имеет лицензию BSD), хотя вам потребуется предоставить / заключить договор на поддержку.

Demi 28.05.2015 02:09

@chris Теперь я понимаю - нельзя выбирать СУБД, потому что за нее надо платить, а значит выставлять ставки.

Demi 31.07.2015 03:33

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

public static String COMMA_DELIMINATOR = ",";
public static String COMMA_SPACE_DELIMINATOR = ", ";
public static String COLIN_DELIMINATOR = ":";

Каждый из них многократно использовался в остальной части приложения для разных целей. COMMA_DELIMINATOR засорял код более чем 200 использованием в 8 различных пакетах.

По крайней мере, что-то подобное легко найти / заменить из источника - тем не менее, мои соболезнования.

Erik Forbes 26.03.2009 22:12

Также - Делиминатор? Я думал, что это написано «разделитель». Delimiter звучит как плохой фильм середины 90-х, в котором каким-то образом было 3 сиквела ...........

Erik Forbes 26.03.2009 22:13

Разделитель III: Возвышение запятых

Rob 26.03.2009 22:19

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

Rob 26.03.2009 22:20

Найти и заменить правильно не так-то просто. Поскольку каждый используется для разных целей. Любой хороший программист сделал бы хотя бы что-то вроде этого: COUNTRY_LIST_DELIM = ... CLASSIFICATION_DELIM = ... и т. д.

KitsuneYMG 26.03.2009 23:56

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

Rich Remer 24.07.2014 00:02

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

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

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

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

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

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

Похоже, никто не упомянул о сортировке, так что я скажу.

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

Я сделал это сам однажды, когда определил, что обычно n = 2. Более поздние улучшения продукта опровергли мою предпосылку, и код был заменен PDQ.

Mark Ransom 22.04.2009 23:10

Да, но приятно время от времени писать что-то на основе алгоритм;)

UpTheCreek 27.07.2010 17:22

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

v.oddou 31.03.2021 08:58

Как насчет экстремизма ЯГНИ. Это форма преждевременной пессимизации. Кажется, что всякий раз, когда вы применяете YAGNI, он вам в конечном итоге нужен, что приводит к 10-кратным усилиям, чтобы добавить его, чем если бы вы добавляли его в начале. Если вы создадите успешную программу, скорее всего, она вам понадобится. Если вы привыкли создавать программы, жизнь которых быстро заканчивается, продолжайте практиковать ЯГНИ, потому что тогда, я полагаю, ЯГНИ.

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

JAL 29.03.2009 11:05

Исследования реальных проектов показывают, что фактический коэффициент между одноразовым и повторно используемым кодом в среднем составляет около 3. Итак, 10 - это просто «ощутимое» значение, но вы правы по своему намерению.

peterchen 29.07.2010 01:55

@peterchen - вы говорите, что исследования показывают, что для написания многократно используемого кода требуется в три раза больше времени, чем для одноразового кода, или что они показывают, что на одноразовый код перерабатывать для многократного использования требуется в три раза больше времени, чем на написание многоразовый код в первую очередь?

Jeff Sternal 29.07.2010 22:01

@jeff: IIRC они сравнили некоторую меру сложности (что бы вы ни думали о них) встроенных сниппетов, которые были перемещены в отдельные методы. Сложность увеличивается из-за поддержки дополнительных случаев, проверки параметров и т. д. (Что заставляет меня предполагать, что методы были довольно небольшими). Разрешите попробовать отыскать ссылку.

peterchen 30.07.2010 02:06

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

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

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

P.s.

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

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

TheBlastOne 07.07.2010 11:39

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

NimChimpsky 14.08.2012 14:52

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

Будь осторожен. Профилирование имеет решающее значение, но это не способ Только выявить проблемы с производительностью.

Jon Adams 27.03.2009 16:59

Что ж, не дразни ... как насчет упоминания некоторых, если другие конкретные способы?

JeffH 27.03.2009 20:43

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

jsight 31.03.2009 01:43

Важен не инструмент, его использует мозг героя (или нет). Это все равно, что сказать: «Я сделаю WTF вашу книгу и не буду читать ее, если вы не проверяете правописание в Word и не показываете мне флажок Word, отображаемый первым.

TheBlastOne 07.07.2010 11:43

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

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

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

Jimmy 27.03.2009 10:23

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

Gabriele D'Antona 27.03.2009 20:48

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

.

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

вместо

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

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


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

Полагаю, я мог бы предложить эту жемчужину:

unsigned long isqrt(unsigned long value)
{
    unsigned long tmp = 1, root = 0;
    #define ISQRT_INNER(shift) \
    { \
        if (value >= (tmp = ((root << 1) + (1 << (shift))) << (shift))) \
        { \
            root += 1 << shift; \
            value -= tmp; \
        } \
    }

    // Find out how many bytes our value uses
    // so we don't do any uneeded work.
    if (value & 0xffff0000)
    {
        if ((value & 0xff000000) == 0)
            tmp = 3;
        else
            tmp = 4;
    }
    else if (value & 0x0000ff00)
        tmp = 2;

    switch (tmp)
    {
        case 4:
            ISQRT_INNER(15);
            ISQRT_INNER(14);
            ISQRT_INNER(13);
            ISQRT_INNER(12);
        case 3:
            ISQRT_INNER(11);
            ISQRT_INNER(10);
            ISQRT_INNER( 9);
            ISQRT_INNER( 8);
        case 2:
            ISQRT_INNER( 7);
            ISQRT_INNER( 6);
            ISQRT_INNER( 5);
            ISQRT_INNER( 4);
        case 1:
            ISQRT_INNER( 3);
            ISQRT_INNER( 2);
            ISQRT_INNER( 1);
            ISQRT_INNER( 0);
    }
#undef ISQRT_INNER
    return root;
}

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

unsigned long isqrt(unsigned long value)
{
    unsigned long tmp = 1, root = 0;
    #define ISQRT_INNER(shift) \
    { \
        if (value >= (tmp = ((root << 1) + (1 << (shift))) << (shift))) \
        { \
            root += 1 << shift; \
            value -= tmp; \
        } \
    }

    ISQRT_INNER (15);
    ISQRT_INNER (14);
    ISQRT_INNER (13);
    ISQRT_INNER (12);
    ISQRT_INNER (11);
    ISQRT_INNER (10);
    ISQRT_INNER ( 9);
    ISQRT_INNER ( 8);
    ISQRT_INNER ( 7);
    ISQRT_INNER ( 6);
    ISQRT_INNER ( 5);
    ISQRT_INNER ( 4);
    ISQRT_INNER ( 3);
    ISQRT_INNER ( 2);
    ISQRT_INNER ( 1);
    ISQRT_INNER ( 0);

#undef ISQRT_INNER
    return root;
}

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

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

unsigned long isqrt(unsigned long value)
{
    unsigned long tmp = 1 << 30, root = 0;

    while (tmp != 0)
    {
        if (value >= root + tmp) {
            value -= root + tmp;
            root += tmp << 1;
        }
        root >>= 1;
        tmp >>= 2;
    }

    return root;
}

Это точно такой же алгоритм, хотя и немного другая реализация, поэтому я полагаю, что он подходит.

Я полагаю, что isqrt() вычисляет floor(sqrt()), но почему этот код работает?

Pablo H 06.07.2018 23:39

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

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

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

У меня был коллега, который пытался перехитрить оптимизатор нашего компилятора C, и программа переписала код, который мог прочитать только он. Одним из его любимых приемов было изменение читаемого метода, например (создание кода):

int some_method(int input1, int input2) {
    int x;
    if (input1 == -1) {
        return 0;
    }
    if (input1 == input2) {
        return input1;
    }
    ... a long expression here ...
    return x;
}

в это:

int some_method() {
    return (input == -1) ? 0 : (input1 == input2) ? input 1 :
           ... a long expression ...
           ... a long expression ...
           ... a long expression ...
}

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

Затем, после этого, по какой-то причине он решил, что ptr->structElement слишком нечитабелен, поэтому он начал заменять все это на (*ptr).structElement, исходя из теории, что он более читабелен и быстрее.

Превращение читаемого кода в нечитаемый - максимум на 1%, а иногда и более медленный код.

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

Michael Dorgan 06.07.2010 18:37

@Michael: Я бы не стал, если бы измерения не указывали, что это Быстрее, а не только короче.

dsimcha 31.08.2010 06:47

В большинстве случаев тернарный оператор более доступен для чтения, чем if. Настаивание на утверждениях над выражениями в C является культурной / религиозной догмой, нет - любой объективной практикой. (Лучшее правило: если вложенный троичный элемент слишком длинный для чтения, вам также не следует использовать if.)

Leushenko 14.04.2015 23:39

Проблема здесь в том, чтобы взять вся функция и заменить его одним оператором, return, тем самым заменяя всю логику всей функции вложенными троичными. Если бы вы это видели, вы бы поняли. Это не религиозная вещь "я ненавижу тернарные операторы". Я не говорю о том, чтобы взять один if в функцию и заменить его тройным. Это нормально и часто более читабельно. Я говорю о замене всего метода из 30+ строк одним оператором return и вложенными тернариями. Никто не считал новый код более читабельным, но один разработчик считал его более быстрым.

Eddie 15.04.2015 03:07

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

v.oddou 31.03.2021 08:50

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

Ответ принят как подходящий

В рамках одного старого проекта мы унаследовали некоторых (в остальном превосходных) программистов встроенных систем, которые имели большой опыт работы с Z-8000.

Нашей новой средой был 32-битный Sparc Solaris.

Один из ребят пошел и поменял все целые на короткие, чтобы ускорить наш код, так как захват 16 бит из ОЗУ был быстрее, чем захват 32 бита.

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

Эй, где ты учился математике? 2 инструкции с 1 доступом к кеш-памяти / ОЗУ, очевидно, быстрее, чем 1 инструкция с 1 доступом к кеш-памяти / ОЗУ!

Razor Storm 24.06.2010 06:24

@RazorStorm На более поздних машинах, где пропускная способность и кеш более важны, будет наоборот. Битовая маска / сдвиг обходятся дешево, но вы хотите как можно больше уместить в кеше, а также минимизировать пропускную способность.

Jed 22.07.2013 22:02

@Jed полностью с вами в этом. Когда вы делаете ориентированный на данные дизайн для вещей, интенсивно использующих память, таких как процесс DSP, многие 128-битные + аппаратные средства (AVX, GPU ...) будут быстрее работать с массивами shorts.

v.oddou 31.03.2021 06:01

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

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

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

   Select uniqueid_col, col2, col3
     from super_big_tbl
 

(псевдокод)


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

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

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

   Select uniqueid_col, col2, col3
     from super_big_tbl
 group by uniqueid_col, col2, col3
   having uniqueid_col = '829-39-3984'

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

   Select uniqueid_col, col2, col3
     from super_big_tbl
    where uniqueid_col = '829-39-3984'
   

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

Tom Leys 06.05.2009 00:50

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

Stradas 21.05.2009 19:43

Масштабируемость - это ошибка, а не функция. Mh.

TheBlastOne 07.07.2010 11:42

Я знаю, что очень поздно к этой теме, но недавно увидел это:

bool isFinished = GetIsFinished();

switch (isFinished)
{
    case true:
        DoFinish();
        break;

    case false:
        DoNextStep();
        break;

    default:
        DoNextStep();
}

Знаете, на случай, если у логического есть какие-то дополнительные значения ...

Верно, ложно, конечно же, FileNotFound

Ikke 01.06.2009 14:55

Эй, у вас всегда должно быть значение по умолчанию / case else / etc. Что происходит, когда какой-нибудь умный человек меняет это логическое значение на перечисление, чтобы отразить другой статус, а затем следующий человек добавляет к перечислению и забывает изменить процедуру? Наличие значения по умолчанию, когда вам не нужно, не требует времени на выполнение и очень мало времени на разработку. Отслеживание случайно введенной логической ошибки, которая возникает во время выполнения ... Это требует времени, денег и репутации. Стежок, сделанный вовремя, стоит девяти.

Oorang 18.03.2010 05:24

@Oorang ... зачем тебе вообще это переключатель? Это логическое значение - все, что требуется, - это if / else.

Damovisa 18.03.2010 06:01

@Damovisa фейспалм ну ... ну ладно :) Пропустил :)

Oorang 03.04.2010 06:45

Нет ничего лучше старого доброго enBooleanDummy. Yes, No и Undefined - возможные значения, по умолчанию - Да ...

user434817 14.02.2011 15:56

Это было Nullable <Boolean> ... :)

George Chakhidze 05.07.2011 12:00

Не совсем преждевременная оптимизация - но определенно ошибочная - это было прочитано на веб-сайте BBC из статьи, посвященной Windows 7.

Mr Curran said that the Microsoft Windows team had been poring over every aspect of the operating system to make improvements. "We were able to shave 400 milliseconds off the shutdown time by slightly trimming the WAV file shutdown music.

Я еще не пробовал Windows 7, поэтому могу ошибаться, но готов поспорить, что есть и другие проблемы, которые более важны, чем время, необходимое для завершения работы. В конце концов, как только я вижу сообщение «Завершение работы Windows», монитор выключается, и я ухожу - какую пользу мне принесут эти 400 миллисекунд?

Вы, вероятно, обнаружите, что другие проблемы не так легко объяснить непрограммистам на веб-сайте BBC.

Tom Leys 06.05.2009 00:52

Вот этот ракурс, который я не рассматривал - может, я начинаю терять цинизм :-)

belugabob 06.05.2009 18:14

Эти 400 мс - это 400 мс потребляемой мощности. Вероятно, незначительно, но, возможно, со временем они прибавятся. Тем не менее, я бы не о чем беспокоился.

ZachS 03.10.2009 02:16

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

James 20.01.2010 22:27

Интересно, что файлы WAV воспроизводятся асинхронно, поэтому до тех пор, пока фанфары выключения короче времени, необходимого для выключения, обрезка файла WAV ничего не дает. И что еще более интересно, если они так сильно оптимизировали завершение работы, почему каждый блок Windows, который я выключаю, нуждается в эонах, пока он действительно не отключится? (За исключением, конечно, большой красной кнопки.)

TheBlastOne 07.07.2010 11:34

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

belugabob 07.07.2010 14:43

Возможно, это не принесет вам пользы, но может быть, планете. Как дошел до Закса, мощность, необходимая для работы ПК в течение 400 мс, x (каждый из 365 дней в году), x (бог знает, сколько миллионов компьютеров) не является незначительной. Как долго они могли обрезать файл WAV? 10 минут? Я бы сказал, что это хорошее решение.

UpTheCreek 27.07.2010 17:14

@UpTheCreek: это хороший момент, который можно экстраполировать на любую из множества операций, которые занимают слишком много времени - например, что, черт возьми, делает Firefox во время запуска ?, сколько циклов процессора (и связанных с ними мощность) тратится на антивирусное сканирование? и т.д, и т.д ...

belugabob 27.07.2010 19:19

Большой номер один на все времена, с которым я снова и снова сталкиваюсь в собственном программном обеспечении:

Не использовать возможности СУБД по причинам «переносимости», потому что «мы можем захотеть перейти к другому поставщику позже».

Читай по губам. Для любых внутренних работ: ЭТО НЕ БУДЕТ!

Это случается. MySQL -> postgresql, поэтому мы ничего не терять.

Thomas 07.07.2009 14:56

Или postgres / postgis -> sqlite / Spaceite ... Это была заноза в заднице ...

Philip 19.09.2011 00:11

это происходит в тестах JUnit

kachanov 24.09.2012 05:54

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

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

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

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

Примеры

У меня есть намеренная ... Однажды я реализовал сортировку с возвратом ... просто как доказательство концепции;)) Само собой разумеется, ее производительность была ужасной.

var stringBuilder = new StringBuilder();
stringBuilder.Append(myObj.a + myObj.b + myObj.c + myObj.d);
string cat = stringBuilder.ToString();

Лучшее использование StringBuilder, которое я когда-либо видел.

Поговорим о «непонятной концепции»! Ух ты!

Eddie 06.07.2010 23:48

Здорово. «Мой руководитель говорит, что я должен использовать класс StringBuilder, если я хочу объединить строки. Это то, что я делаю. Так что же не так?» Ржу не могу...

TheBlastOne 17.08.2010 13:01

Как насчет ПОБИ - пессимизация явно умышленно?

Мой коллега в 90-х устал от того, что генеральный директор пинал ему задницу только потому, что генеральный директор проводил первый день каждого выпуска программного обеспечения ERP (нестандартного), выявляя проблемы производительности в новых функциях. Даже если новые функциональные возможности сокрушили гигабайты и сделали невозможное возможным, он всегда находил какие-то детали или даже, казалось бы, серьезную проблему, над которой можно было ныть. Он считал, что хорошо разбирается в программировании, и получил свое удовольствие, надрывая задницы программистам.

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

Пока в одном выпуске он не поместил много вызовов функций Delay (200) (это был Delphi) в новый код. Прошло всего 20 минут после запуска, и ему было приказано явиться в офис генерального директора, чтобы лично принести свои запоздалые оскорбления.

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

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

Это был первый (и единственный) раз, когда злой генеральный директор сказал «отличная работа!» ему. Это все, что имеет значение, верно?

Это был настоящий ПОБИ.

Но это также своего рода оптимизация социальных процессов, так что это на 100% нормально.

Я думаю.

Я помню, как кто-то писал о приложении для обработки данных, которое продавалось на разных уровнях, где «Lite» мог обрабатывать только несколько наборов данных в секунду, а версия «superduper» - тысячи. Единственное отличие исходного кода - это Sleep (N).

peterchen 29.07.2010 01:53

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

RCIX 29.07.2010 03:02

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

TheBlastOne 17.08.2010 13:15

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

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

Чтобы исправить это, я удалил компоненты многопоточности и очистил ввод-вывод. Без каких-либо других изменений время выполнения набора данных из 150 источников упало ниже 10 минут на моей машине и с бесконечности до менее получаса на средней машине компании.

Я просто предотвращаю это в проекте сегодня. Теперь я знаю, что сделал правильный выбор.

deadalnix 06.09.2011 00:44

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

Кто-то в моем отделе однажды написал струнный класс. Интерфейс похож на CString, но без зависимости от Windows.

Одна из «оптимизаций», которую они сделали, заключалась в том, чтобы нет выделял больше памяти, чем необходимо. По-видимому, не понимая, что такие классы, как std::string, выделяют избыточную память, заключаются в том, что последовательность операций += может выполняться за O (n) раз.

Вместо этого каждый звонок += принудительно перераспределяет, что превращает повторяющиеся добавления в O (n²) Алгоритм Шлемиля Художника.

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

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;

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

while true; do echo 3 > /proc/sys/vm/drop_caches; sleep 3600; done

Это заставляло ядро ​​тратить время на очистку дискового кеша, и как только это удалось, все работало медленно, пока кеш не был заполнен заново. Вызвано неправильным представлением о том, что кеш-память диска препятствует доступу памяти для использования приложениями.

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