Что программисты «микрооптимизируют» на сегодня? [закрыто]

14

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

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

Например: программисты тратят время на обобщение частных методов, которые вызываются только из одного места? Потрачено ли время на сокращение данных тестового примера? Программисты (все еще) чрезмерно обеспокоены сокращением строк кода?

Ниже приведены два замечательных примера того, что я ищу: (1) тратить время на поиск правильных имен переменных, даже переименовывая все; и (2) устранение даже незначительного и незначительного дублирования кода.


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

Макнейл
источник
Смотрите здесь: programmers.stackexchange.com/questions/14856/…
Роберт Харви
@Macneil, я не знаю, для чего другие программисты микрооптимизируют, но у меня не так много времени для этого. Мои коллеги тоже заняты (только мои 2 цента).
Работа
@Job: Вы никогда не видели, чтобы кто-то тратил свое время, меняя код без причины? Считай, что тебе повезло. Ниже приведены два замечательных примера: имена переменных и незначительное дублирование кода.
Макнейл
1
Вопрос, как он сформулирован в настоящее время, является улучшением. Я не могу убрать закрытое голосование, но оно пройдет через несколько дней. На самом деле, вопрос привлекает довольно хорошие ответы.
Роберт Харви
1
Кстати, любая лучшая практика может быть доведена до такой степени, что она больше не производит ценности.
Роберт Харви

Ответы:

22

Форматирование кода

Don't     get    me   wrong             ,
code      should be   consistent        & 
readable                                , 
but       some   take it         too far.
JeffO
источник
Ах да, старые добрые типы переменных и имена переменных нуждаются в своих собственных столбцах в серии объявлений переменных. Ой! Забыл лишний ряд для =и четвертый для инициализаторов!
Макнейл
[Черт, возбуждаю, но мой дневной лимит достигнут ...]
Макнейл
3
Наши профессора заставили нас отформатировать код для наших заданий таким образом. Мне потребовались годы, чтобы избавиться от этой привычки.
Оливер Вейлер
О, Боже.
Над
2
+1 Однажды я работал с библиотекой, в которой разработчик отказался сделать свой код const-правильным, потому что он испортил его код в формате столбцов ...
Дин Хардинг,
20

Раньше я писал много ассемблера назад. Дело не только в том, что компиляторы стали лучше, но и в том, что большая часть аппаратного обеспечения теперь имеет много логики, предназначенной для неупорядоченного выполнения кода. Настоящая микро-проблема - это планирование, большинство компьютерных инструкций требуют нескольких машинных часов для получения результата, а загрузка памяти, которая пропускает кеш, может занять несколько сотен! Таким образом, идея состояла в том, чтобы запланировать другие инструкции, чтобы сделать что-то полезное, вместо ожидания результата. А современные машины могут выдавать несколько инструкций за такт. Как только мы начали использовать HW для нестандартного исполнения, я обнаружил, что попытки добиться высокой производительности с помощью ручного кодирования стали игрой в кружки. Во-первых, вышедший из строя HW не будет выполнять инструкции в тщательно продуманном порядке, новая причудливая архитектура HW позволила снизить количество неоптимального планирования программного обеспечения настолько, что компилятор обычно находился в пределах нескольких процентов от вашей производительности. Также я узнал, что компиляторы теперь реализуют хорошо известные, но сложные приемы генерации, такие как развертывание, загрузка снизу, конвейерная обработка программного обеспечения и т. Д. Суть в том, что вам нужно действительно очень усердно работать, пропустить некоторые из этих приемов, и компилятор вас превзойдет. Используйте их все, и количество необходимых вам ассемблерных инструкций увеличится в несколько раз!

Возможно, что еще более важно, большинство проблем с производительностью связаны не с частотой команд, а с передачей данных в ЦП. Как я упоминал выше, задержка памяти теперь составляет сотни циклов, и процессор может выполнять несколько инструкций за такт, поэтому, если программа - и особенно структуры данных не спроектированы так, чтобы частота обращений в кэш-память была чрезвычайно высокой, микротонирование по команде уровень не будет иметь никакой выгоды. Так же, как военные говорят, что любители говорят о тактике, профессионалы говорят о логистике. Программирование производительности в настоящее время составляет более 90% логистики (перемещение данных). И это трудно определить количественно, поскольку современное управление памятью обычно имеет несколько уровней кэша, а страницы виртуальной памяти обрабатываются аппаратным модулем, называемым TLB. Кроме того, выравнивание адресов низкого уровня становится важным, так как фактические данные передаются не в байтах, или даже 64-битные long-long, но они приходят в единицах строк кэша. Тогда у большинства современных машин есть оборудование, которое пытается предсказать, какая строка кэша пропустит вас, возможно, потребуется в ближайшем будущем, и выполнить автоматические предварительные выборки, чтобы поместить их в кэш. Таким образом, реальность такова, что с современными процессорами модели производительности настолько сложны, что их практически невозможно понять. Даже подробные аппаратные симуляторы никогда не смогут соответствовать точной логике чипов, поэтому точная настройка просто невозможна.

Есть еще место для ручного кодирования. Математические библиотеки (как, например, функция exp), так же как и более важные операции линейной алгебры (например, умножение матриц), все еще обычно пишутся вручную экспертами, которые работают на поставщика оборудования (то есть Intel, AMD или IBM), но они, вероятно, только нужна пара первоклассных ассемблерных программистов на мегакомпьютерную корпорацию.

Омега Центавра
источник
1
Ручное кодирование становится все труднее для людей, работающих вне поставщиков ЦП, поскольку задача все больше зависит от инсайдерских знаний и специальных инструментов вендора (компиляторов и профилировщиков). spiral.net пытается смоделировать оптимизацию процессора и автоматизировать поиск оптимальных решений.
rwong
Многие компьютерные языки подталкивают программистов к бессмысленной микрооптимизации, из-за чего трудно использовать двойную точность для вычислений, результаты которых будут отображаться float. По какой-то причине я не могу понять, многие люди думают, что это хорошо.
суперкат
10

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

Это идет немного дальше, когда я пытаюсь привести все произведения (программу) в один и тот же лингвистический стиль. Иногда мое мнение меняется, и я пересматриваю книгу. :)

Нет, это занимает столько времени. Это довольно редко. Но мне нравится сохранять хорошую грамматику в моих программах.


источник
3
Называть сложно. Следовательно, вы должны рефакторинг имени, когда вы думаете о гораздо лучшем. Обратите внимание, что это захватывает умственное усилие, и, надеюсь, кристаллизует «почему» тоже.
1
Это очень левая вещь (левая сторона вашего мозга отвечает за обработку языка). Как программист с правильным умом, я склонен тратить гораздо меньше времени на беспокойство о семантике и больше времени на размышления о том, как все части сочетаются друг с другом.
Джейсон Бейкер
7
Наименование переменных и методов является важной частью ремонтопригодности. Один должен тратить время на обдумывание об именах, так что через 5 лет, человек , сохраняя код имеет более легкое время с ним.
GrandmasterB
@ Grandmaster: Не могу согласиться больше.
Роберт Харви
4
@ right-brainers: Пожалуйста, напишите код для lef-tbrainers, чтобы я тоже мог прочитать ваш код
Хуан Мендес
10

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

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

Тем не менее, в мою защиту, если нереалистичное станет реальностью ... оптимизация больше не является "микро". Обратите внимание, я не сказал невозможно , но нереально .

Конечно, требования имеют приоритет.

Тим Пост
источник
1
Я работал в компании, которая затонула из-за этого.
Генри
2
@ Генри - обещаю, это был не я :)
Тим Пост
1
@ Генри: Вы имеете в виду, что они потратили время на оптимизацию под вещи, которые, вероятно, никогда бы не произошли, или они не думали о вещах, которые, вероятно, никогда не произойдут ... пока они не произошли, и не стало слишком поздно?
Дин Хардинг
2
@Henry: Если у компании есть продукт с высокой степенью масштабируемости и он все еще не работает, то это вина продаж и маркетинга (не нацеливание на крупных клиентов и неправильная оценка), а не разработка.
Руонг
1
Компания потратила слишком много времени на разработку системы для миллионов пользователей, когда у них не было одного пользователя. Должно быть, это была ошибка маркетинга. Да, давайте обвинять маркетинг, эти парни идиоты.
Генри
8

Я думаю, что потратил впустую недели потраченного времени на обработку обработчиков исключений Java.

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

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

В какой-то момент я заменил все строки concat на, String.formatчтобы ошибка файла не приводила к лишним объектам в куче. Это была пустая трата времени.

Сэл
источник
3
Это важная работа. Цена ошибки = ваше сообщение об ошибке, которое будет отображаться в ежедневном WTF.
Steve314
7

Я полагаю, я слишком обеспокоен LOC. Не столько самих LOC, сколько количество утверждений и даже больше повторяющихся утверждений. У меня аллергия на дубликат кода. В целом, я люблю рефакторинг, но я полагаю, что около 50% того, что я делаю, не делает код значительно лучше.

back2dos
источник
4
+1 за «У меня аллергия на повторяющийся код». Смотрите также мой ответ здесь: programmers.stackexchange.com/questions/14610/…
Macneil
Думая об этом - у меня есть эта проблема с циклами, которая связана с точкой зрения Кнута о goto, и иногда приходится торговать циклом, двумя или каким-либо дублирующим кодом для написания структурированного кода. Я буду использовать goto в очень редких случаях (наиболее распространенный = сгенерированный код), но моя разновидность этого беспорядка - это тратить время на беспокойство и возиться с циклом, бесконечно пытаясь устранить тривиальную неэффективность, но при этом сохранить код читабельным.
Steve314
5

Чтение файла строка за строкой вместо простого чтения всей строки в строку и обработки строки за один дубль.

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

Да, это, вероятно, не имеет смысла, если размер файла составляет 3 ГБ, но большинство файлов не такие большие (по крайней мере, не те, с которыми я работаю ;-)).

Оливер Вейлер
источник
3
Даже если он составляет 3 ГБ или более, 64-разрядная машина может обрабатывать его с помощью виртуальной памяти. Используйте файл с отображенной памятью, и он даже не будет читать какую-либо часть вашего файла, пока не понадобится. Имейте в виду, даже это микрооптимизация в обычном случае.
Steve314
3

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

Точно так же, когда я перешел к написанию на C, было довольно легко выполнить лучшую работу, чем компиляторы C, но каждый год Borland, Microsoft или кто-то выпускали новую улучшенную версию, которая пинала предыдущую по всей комнате. Я начал обращать внимание на фактический код ассемблера, который испускал компилятор, и, черт побери, если он не писал какой-то хороший и сложный код, разворачивал циклы, перемещал переменные вне циклов и т. Д.

Сейчас я пишу на более высоких языках, таких как Perl, Python и Ruby. Я использую некоторые приемы компилятора, такие как развертывание циклов, если это имеет смысл, перемещение статических переменных за пределы циклов и т. Д., Но я не беспокоюсь об этом почти так же сильно, потому что сейчас процессоры стали немного быстрее. Если приложение неожиданно перетаскивается, тогда я использую профилировщик и посмотрю, что я могу найти, а затем, если что-то можно улучшить, я начну тестировать различные способы, которые я могу придумать, чтобы сделать что-то быстрее, а затем посмотрю, как это можно улучшить. масштабируется

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

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

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

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

Кевин Канту
источник
2

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

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

Джейсон Бейкер
источник
Зачем программистам. быть другим? В чем разница, пожалуйста.
Дэн Розенстарк
@ Яр - Почему программисты отличаются от других?
Джейсон Бейкер
почему programmers.= programmers.stackexchange.comбудет отличаться от любого места , которое вы работали , где вы должны были объяснить разницу между этими двумя понятиями? Пожалуйста, объясните разницу.
Дэн Розенстарк
@ Яр - я не знаю, что будет. На самом деле, поскольку цель programmers.se состоит в том, чтобы помочь программистам объединять знания, я надеюсь, что это не так, что люди могут быть хоть немного просветлены моим ответом.
Джейсон Бейкер
2
Так в чем же разница между простотой и простотой?
Дэн Розенстарк
2

Я за принцип «не оптимизируй, если не надо». И я все за профиль-первый принцип. И в принципе, я буду оптимизировать только то, что будет иметь значение.

Это в принципе. Но принцип лжец.

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

О - и тут есть логика «Я пишу это - конечно, это важная библиотека».

Ох - и кстати. Я никогда еще не использовал профилировщик для оптимизации. Не имею доступа к коммерческому, и никогда не создавал мотивацию, чтобы выяснить gprof.

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

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

РЕДАКТИРОВАТЬ

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

Steve314
источник
+1 Ах да! Этот класс анализирует очень специфичные и причудливые аргументы командной строки моего приложения, но позвольте мне отформатировать и полностью документировать его, когда Javadoc, потому что наверняка другие будут использовать это в течение многих лет! [Нужно будет поднять голос позже, моя дневная кепка достигнута.]
Макнейл
@Macneil - это Doxygen, я хочу, чтобы ты знал. С каждой опцией, которую я нахожу включенной, каждая маленькая функция «документируется» в мельчайших деталях, в комплекте с дюжиной симпатичных графиков GraphViz. Действительно помогает всем понять, насколько важен мой код - и распечатка может обставить довольно большой офисный блок.
Steve314
1

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

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

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

Твиттер и Фейсбук приходят на ум :-)

Стивен С
источник
Привет, Стивен, это отличный комментарий к микрооптимизации, но видишь ли ты современные эквиваленты? [Facebook и Twitter не являются «лучшими практиками», которые можно
зайти
Это все еще имеет смысл. Время на часах может быть на несколько порядков меньше, но код на порядки больше ...
hplbsh
@Stuart - это означает, что кода для микрооптимизации будет на несколько порядков больше, что просто не масштабируется.
Стивен С.