Хорошо, вы определяете проблему там, где, казалось бы, не так много возможностей для улучшения. По моему опыту, это довольно редко. Я попытался объяснить это в статье доктора Доббса в ноябре 1993 года, начав с традиционно хорошо спроектированной нетривиальной программы без очевидных потерь и проводя серию оптимизаций, пока время настенных часов не уменьшилось с 48 секунд. до 1,1 секунды, и размер исходного кода был уменьшен в 4 раза. Мой диагностический инструмент был этим . Последовательность изменений была такой:
Первой найденной проблемой было использование кластеров списков (теперь называемых «итераторами» и «классами контейнеров»), занимающих более половины времени. Они были заменены довольно простым кодом, сократив время до 20 секунд.
В настоящее время крупнейший хронометрист больше строит списки. В процентном отношении он был не таким большим, но теперь это потому, что большая проблема была устранена. Я нахожу способ ускорить его, и время падает до 17 секунд.
Сейчас труднее найти явных виновников, но есть несколько мелких, с которыми я могу что-то сделать, и время сокращается до 13 секунд.
Теперь я, кажется, ударил стену. Образцы рассказывают мне точно, что он делает, но я не могу найти ничего, что можно улучшить. Затем я размышляю над базовым дизайном программы, ее структурой, управляемой транзакциями, и спрашиваю, действительно ли весь поиск по списку, который она выполняет, требует выполнения требований задачи.
Затем я натолкнулся на редизайн, где программный код фактически генерируется (с помощью макросов препроцессора) из меньшего набора источников, и в котором программа не постоянно выясняет вещи, которые, как знает программист, довольно предсказуемы. Другими словами, не «интерпретировать» последовательность действий, «скомпилировать» ее.
- Этот редизайн сделан, сжатие исходного кода в 4 раза, а время сокращено до 10 секунд.
Теперь, потому что он становится таким быстрым, его сложно отобрать, поэтому я даю ему в 10 раз больше работы, но следующие времена основаны на исходной рабочей нагрузке.
Больше диагностики показывает, что он проводит время в управлении очередями. В подкладке это сокращает время до 7 секунд.
Теперь большое время занимает диагностическая печать, которую я делал. Флеш - 4 секунды.
В настоящее время крупнейшими потребителями времени являются звонки на malloc и бесплатные звонки . Перезарядка объектов - 2,6 секунды.
Продолжая пробовать, я все еще нахожу операции, которые не являются строго необходимыми - 1,1 секунды.
Общий коэффициент ускорения: 43,6
Сейчас нет двух одинаковых программ, но в не игрушечных программах я всегда видел такой прогресс. Сначала вы получаете легкие вещи, а затем более сложные, пока не дойдете до точки убывающей отдачи. Тогда понимание, которое вы получите, может привести к редизайну, начав новый раунд ускорений, пока вы снова не достигнете убывающей отдачи. Теперь это точка , в которой она может иметь смысл усомниться в том , ++i
или i++
или for(;;)
или while(1)
быстрее: виды вопросов , которые я вижу так часто на переполнение стека.
PS Может возникнуть вопрос, почему я не использовал профилировщик? Ответ заключается в том, что почти каждая из этих «проблем» была сайтом вызова функций, которые точно определяют образцы стека. Профилировщики даже сегодня едва ли приходят к мысли, что операторы и инструкции вызова более важны для поиска и легче исправить, чем целые функции.
Я на самом деле создал профилировщик, чтобы сделать это, но для реального унизительного и близкого отношения к тому, что делает код, ничто не заменит попадание в него пальцев. Дело не в том, что количество выборок невелико, поскольку ни одна из обнаруженных проблем не настолько мала, чтобы их можно было легко пропустить.
ДОБАВЛЕНО: jerryjvl запросил несколько примеров. Здесь первая проблема. Он состоит из небольшого количества отдельных строк кода, занимающих более половины времени:
/* IF ALL TASKS DONE, SEND ITC_ACKOP, AND DELETE OP */
if (ptop->current_task >= ILST_LENGTH(ptop->tasklist){
. . .
/* FOR EACH OPERATION REQUEST */
for ( ptop = ILST_FIRST(oplist); ptop != NULL; ptop = ILST_NEXT(oplist, ptop)){
. . .
/* GET CURRENT TASK */
ptask = ILST_NTH(ptop->tasklist, ptop->current_task)
Они использовали кластер списков ILST (аналогичный списковому классу). Они реализованы обычным способом, причем «скрытие информации» означает, что пользователям класса не нужно было заботиться о том, как они были реализованы. Когда эти строки были написаны (примерно из 800 строк кода), не было мысли о том, что это может быть «узким местом» (я ненавижу это слово). Это просто рекомендуемый способ сделать что-то. Оглядываясь назад , легко сказать, что этого следовало избегать, но по моему опыту все проблемы с производительностью таковы. В общем, хорошо стараться избегать проблем с производительностью. Еще лучше найти и исправить те, которые были созданы, даже если их «следовало бы избежать» (задним числом).
Вот вторая проблема, в двух отдельных строках:
/* ADD TASK TO TASK LIST */
ILST_APPEND(ptop->tasklist, ptask)
. . .
/* ADD TRANSACTION TO TRANSACTION QUEUE */
ILST_APPEND(trnque, ptrn)
Это строит списки, добавляя элементы к своим целям. (Исправление состояло в том, чтобы собрать элементы в массивах и создать списки сразу.) Интересно то, что эти операторы только стоят (то есть находились в стеке вызовов) 3/48 первоначального времени, поэтому их не было На самом деле большая проблема в начале . Тем не менее, после устранения первой проблемы они стоили 3/20 времени, и теперь стали «более крупной рыбой». В общем, так оно и есть.
Я мог бы добавить, что этот проект был извлечен из реального проекта, в котором я помог. В этом проекте проблемы с производительностью были гораздо более серьезными (как и ускорения), такими как вызов подпрограммы доступа к базе данных во внутреннем цикле, чтобы увидеть, была ли задача завершена.
ДОБАВЛЕННАЯ ССЫЛКА: Исходный код, как оригинальный, так и переработанный, можно найти на сайте www.ddj.com за 1993 год, в файле 9311.zip, файлах slug.asc и slug.zip.
РЕДАКТИРОВАТЬ 2011/11/26: В настоящее время существует проект SourceForge, содержащий исходный код в Visual C ++ и подробное описание его настройки. Он проходит только первую половину сценария, описанного выше, и не следует точно такой же последовательности, но все равно получает ускорение на 2-3 порядка.
Предложения:
Недостатки : если на самом деле используются несколько предварительно вычисленных значений, это может ухудшить ситуацию, также поиск может занять значительную память.
Недостатки : написание дополнительного кода означает большую площадь для ошибок.
Недостатки : ну ... ответ не будет точным.
источник
Когда вы больше не можете улучшить производительность - посмотрите, можно ли вместо этого улучшить воспринимаемую производительность.
Возможно, вам не удастся ускорить алгоритм fooCalc, но часто есть способы сделать ваше приложение более отзывчивым для пользователя.
Несколько примеров:
Это не сделает вашу программу быстрее, но она может сделать ваших пользователей счастливее с вашей скоростью.
источник
Я провожу большую часть своей жизни именно в этом месте. Широкие штрихи - запустить ваш профилировщик и записать его:
__restrict
обильно, чтобы пообещать компилятору о псевдонимах.И еще одна вещь, которую я люблю делать:
источник
Examples on the PowerPC ...
<- То есть некоторые реализации PowerPC. PowerPC - это ISA, а не процессор.lea
.Брось больше оборудования на это!
источник
Больше предложений:
Избегайте ввода / вывода . Любой ввод / вывод (диск, сеть, порты и т. Д.) Всегда будет выполняться намного медленнее, чем любой код, выполняющий вычисления, поэтому избавьтесь от любого ввода / вывода, который вам строго не нужен.
Переместить ввод-вывод вперед : загрузите все данные, которые вам понадобятся для предварительного расчета, чтобы у вас не было повторных ожиданий ввода-вывода в ядре критического алгоритма (и, возможно, в результате повторного поиск диска, при загрузке всех данных одним попаданием можно избежать поиска).
Задержка ввода / вывода : не записывайте свои результаты до завершения вычислений, сохраняйте их в структуре данных и затем выводите их за один раз в конце, когда тяжелая работа завершена.
Потоковый ввод / вывод : для тех, кто достаточно смел, объедините «I / O заранее» или «Delay I / O» с фактическим расчетом, переместив загрузку в параллельный поток, чтобы во время загрузки большего количества данных вы могли работать вычисляя данные, которые у вас уже есть, или когда вы вычисляете следующую партию данных, вы можете одновременно выписать результаты из последней партии.
источник
mmap()
для ввода, делайте соответствующиеmadvise()
вызовы и используйтеaio_write()
для записи больших кусков вывода (= несколько МБ).Поскольку многие проблемы с производительностью связаны с проблемами с базой данных, я дам вам несколько конкретных вещей, на которые следует обратить внимание при настройке запросов и хранимых процедур.
Избегайте курсоров в большинстве баз данных. Избегайте зацикливания. В большинстве случаев доступ к данным должен быть основан на наборе, а не на записи путем обработки записи. Это включает в себя не повторное использование одной хранимой процедуры записи, когда вы хотите вставить 1 000 000 записей одновременно.
Никогда не используйте select *, возвращайте только те поля, которые вам действительно нужны. Это особенно верно, если есть какие-либо объединения, поскольку поля объединения будут повторяться и, следовательно, вызывать ненужную нагрузку как на сервер, так и на сеть.
Избегайте использования коррелированных подзапросов. Используйте объединения (включая объединения с производными таблицами, где это возможно) (я знаю, что это верно для Microsoft SQL Server, но проверяйте рекомендации при использовании другого бэкэнда).
Индекс, индекс, индекс. И обновите эту статистику, если она применима к вашей базе данных.
Сделайте запрос саргным . Значение означает избегать вещей, которые делают невозможным использование индексов, таких как использование подстановочного знака в первом символе предложения like или функции в соединении или в качестве левой части инструкции where.
Используйте правильные типы данных. Математику даты в поле даты быстрее выполнить, чем пытаться преобразовать строковый тип данных в тип данных date, а затем выполнить расчет.
Никогда не вставляйте петли любого рода в курок!
В большинстве баз данных есть способ проверить, как будет выполняться выполнение запроса. В Microsoft SQL Server это называется планом выполнения. Сначала проверьте их, чтобы увидеть, где находятся проблемные зоны.
При определении того, что нужно оптимизировать, учитывайте, как часто выполняется запрос, а также сколько времени он занимает. Иногда вы можете добиться большей производительности от небольшой настройки запроса, который выполняется миллионы раз в день, чем от стирания времени с запроса long_running, который выполняется только раз в месяц.
Используйте какой-нибудь инструмент профилировщика, чтобы узнать, что на самом деле отправляется в базу данных и из нее. Я могу вспомнить один раз в прошлом, когда мы не могли понять, почему страница загружалась так медленно, когда хранимая процедура была быстрой, и обнаружила в результате профилирования, что веб-страница запрашивала запрос много раз, а не один раз.
Профилировщик также поможет вам найти, кто кого блокирует. Некоторые запросы, которые выполняются быстро при выполнении в одиночку, могут стать очень медленными из-за блокировок других запросов.
источник
Единственный самый важный ограничивающий фактор сегодня - ограниченная память . Многоядерные процессоры только усугубляют ситуацию, поскольку пропускная способность разделяется между ядрами. Кроме того, ограниченная область микросхем, предназначенная для реализации кэшей, также поделена между ядрами и потоками, что еще больше усугубляет эту проблему. Наконец, межкристальная сигнализация, необходимая для поддержания согласованности различных кэшей, также увеличивается с увеличением числа ядер. Это также добавляет штраф.
Это те эффекты, которыми вы должны управлять. Иногда через микро управление вашим кодом, но иногда через тщательное рассмотрение и рефакторинг.
Многие комментарии уже упоминают код, дружественный к кешу. Есть по крайней мере два разных вида этого:
Первая проблема, в частности, связана с тем, чтобы сделать ваши шаблоны доступа к данным более регулярными, чтобы аппаратный предварительный сборщик работал эффективно. Избегайте динамического выделения памяти, которое распределяет ваши объекты данных в памяти. Используйте линейные контейнеры вместо связанных списков, хэшей и деревьев.
Вторая проблема связана с улучшением повторного использования данных. Измените ваши алгоритмы для работы с подмножествами ваших данных, которые помещаются в доступный кеш, и максимально используйте эти данные, пока они еще находятся в кеше.
Более плотная упаковка данных и уверенность в том, что вы используете все данные в строках кэша в горячих циклах, помогут избежать этих других эффектов и позволят разместить более полезные данные в кэше.
источник
источник
Хотя мне нравится ответ Майка Данлавей, на самом деле это действительно хороший ответ с подтверждающим примером, я думаю, что его можно выразить очень просто так:
Сначала выясните, что занимает наибольшее количество времени, и поймите, почему.
Это процесс идентификации временных свиней, который помогает вам понять, где вы должны уточнить свой алгоритм. Это единственный всеобъемлющий языковой независимый ответ, который я могу найти на проблему, которая уже должна быть полностью оптимизирована. Также предполагается, что вы хотите быть независимым от архитектуры в своем стремлении к скорости.
Таким образом, хотя алгоритм может быть оптимизирован, его реализация не может быть. Идентификация позволяет узнать, какая часть является какой: алгоритм или реализация. Так что, какое бы время ни заняло у вас больше всего времени, это ваш главный кандидат на проверку. Но поскольку вы говорите, что хотите выжать последние несколько процентов, возможно, вы захотите также изучить меньшие части, части, которые вы сначала не исследовали так внимательно.
Наконец, немного проб и ошибок с показателями производительности различных способов реализации одного и того же решения или, возможно, различных алгоритмов, может помочь понять, что помогает тратить время и экономить время.
HPH, asoudmove.
источник
Вам, вероятно, следует рассмотреть «перспективу Google», то есть определить, каким образом ваше приложение может стать в значительной степени распараллеленным и параллельным, что неизбежно также будет означать, что в какой-то момент вы захотите распределить ваше приложение по различным машинам и сетям, чтобы в идеале оно могло масштабироваться почти линейно. с оборудованием, которое вы бросаете на это.
С другой стороны, люди из Google также известны тем, что используют много рабочей силы и ресурсов для решения некоторых проблем в проектах, инструментах и инфраструктуре, которые они используют, таких как, например, оптимизация всей программы для gcc с помощью специальной группы инженеров. взлом gcc внутренностей, чтобы подготовить его к типичным сценариям использования Google.
Точно так же профилирование приложения больше не означает просто профилировать программный код, но также и все окружающие его системы и инфраструктуру (например, сети, коммутаторы, сервер, RAID-массивы) для выявления избыточности и потенциала оптимизации с точки зрения системы.
источник
источник
источник
Разделяй и властвуй
Если обрабатываемый набор данных слишком велик, переберите его фрагменты. Если вы сделали свой код правильно, реализация должна быть легкой. Если у вас есть монолитная программа, теперь вы знаете лучше.
источник
Прежде всего, как уже упоминалось в нескольких предыдущих ответах, узнайте, что ограничивает вашу производительность - память, процессор, сеть, база данных или что-то еще. В зависимости от этого ...
... если это память - найди одну из книг, написанных давным-давно Кнутом, одну из серии "Искусство компьютерного программирования". Скорее всего, речь идет о сортировке и поиске - если у меня не в порядке с памятью, вам придется выяснить, в чем он говорит о том, как бороться с медленным хранением данных на ленте. Мысленно преобразуйте его пару память / лента в вашу пару кэш / основная память (или в пару кэш L1 / L2) соответственно. Изучите все приемы, которые он описывает, - если вы не нашли решения, которое решает вашу проблему, то наймите профессионального компьютерного ученого для проведения профессионального исследования. Если у вас случайно возникла проблема с памятью из-за FFT (при выполнении бабочек из radix-2 в кэше отсутствует обратный бит), не нанимайте ученого - вместо этого вручную оптимизируйте проходы по одному, пока либо победить, либо попасть в тупик. Ты упомянулвыжать до последних нескольких процентов, верно? Если их действительно мало, вы, скорее всего, победите.
... если это процессор - переключитесь на язык ассемблера. Изучите спецификацию процессора - что нужно, тики , VLIW, SIMD. Вызовы функций, скорее всего, являются заменяемыми тик-едоками. Изучите цикл преобразований - конвейер, разверните. Умножения и деления могут быть заменяемыми / интерполированными со сдвигами битов (умножения на маленькие целые числа могут быть заменены сложениями). Попробуйте трюки с более короткими данными - если вам повезет, одна инструкция с 64 битами может оказаться заменяемой двумя на 32 или даже 4 на 16 или 8 на 8 битами. Попробуйте также дольшеданные - например, ваши вычисления с плавающей точкой могут оказаться медленнее, чем двойные вычисления на конкретном процессоре. Если у вас есть тригонометрические вещи, боритесь с ними с заранее рассчитанными таблицами; также имейте в виду, что синусоидальное значение может быть заменено этим значением, если потеря точности находится в допустимых пределах.
... если это сеть - подумайте о сжатии данных, которые вы передаете по ней. Заменить передачу XML двоичным. Протоколы обучения. Попробуйте UDP вместо TCP, если вы можете как-то справиться с потерей данных.
... если это база данных, хорошо, зайдите на любой форум базы данных и попросите совета. Сетка данных в памяти, оптимизация плана запросов и т. Д. И т. Д.
HTH :)
источник
Кэширование! Дешевый способ (с точки зрения программиста) сделать почти все быстрее - добавить слой абстракции кэширования в любую область перемещения данных вашей программы. Будь то ввод / вывод или просто передача / создание объектов или структур. Часто к фабричным классам и читателям / писателям легко добавлять кэши.
Иногда кеш не принесет вам большой пользы, но это простой способ просто добавить кеширование и отключить его там, где это не поможет. Я часто обнаруживал, что это дает огромную производительность без микроанализа кода.
источник
Я думаю, что это уже было сказано по-другому. Но когда вы имеете дело с алгоритмом, интенсивно использующим процессор, вы должны упростить все внутри самого внутреннего цикла за счет всего остального.
Некоторым это может показаться очевидным, но я стараюсь сосредоточиться на этом, независимо от языка, с которым я работаю. Например, если вы имеете дело с вложенными циклами и находите возможность снизить уровень кода, в некоторых случаях вы можете значительно ускорить код. В качестве другого примера, есть такие мелочи, как работа с целыми числами вместо переменных с плавающей запятой, когда это возможно, и использование умножения вместо деления, когда это возможно. Опять же, это вещи, которые следует учитывать для вашего самого внутреннего цикла.
Иногда вам может быть полезно выполнять математические операции над целым числом во внутреннем цикле, а затем уменьшать его до переменной с плавающей запятой, с которой вы сможете работать впоследствии. Это пример пожертвования скоростью в одной секции, чтобы улучшить скорость в другой, но в некоторых случаях отдача может стоить того.
источник
Я провел некоторое время, работая над оптимизацией бизнес-систем клиент / сервер, работающих в сетях с низкой пропускной способностью и с большими задержками (например, спутниковые, удаленные, оффшорные), и смог добиться значительного улучшения производительности с помощью достаточно повторяемого процесса.
Мера : Начните с понимания базовой емкости и топологии сети. Поговорите с соответствующими сетевиками в бизнесе и воспользуйтесь базовыми инструментами, такими как ping и traceroute, чтобы установить (как минимум) задержку сети из каждого клиентского местоположения в течение типичных периодов работы. Затем выполните точные измерения времени определенных функций конечного пользователя, которые отображают проблемные симптомы. Запишите все эти измерения, а также их местоположение, даты и время. Подумайте о том, чтобы встроить функциональность «тестирования производительности сети» для конечного пользователя в ваше клиентское приложение, что позволит вашим опытным пользователям участвовать в процессе улучшения; Подобное расширение их полномочий может оказать огромное психологическое воздействие, когда вы имеете дело с пользователями, разочарованными неэффективной системой.
Анализ : использование любого и всех доступных методов ведения журнала, чтобы точно установить, какие данные передаются и принимаются во время выполнения затронутых операций. В идеале ваше приложение может собирать данные, передаваемые и получаемые как клиентом, так и сервером. Если они также включают временные метки, даже лучше. Если достаточное ведение журнала недоступно (например, закрытая система или невозможность развертывания изменений в производственной среде), используйте сетевой анализатор и убедитесь, что вы действительно понимаете, что происходит на сетевом уровне.
Кэш : найдите случаи, когда статические или редко изменяемые данные передаются многократно, и продумайте соответствующую стратегию кэширования. Типичные примеры включают значения «списка выбора» или другие «ссылочные объекты», которые могут быть удивительно большими в некоторых бизнес-приложениях. Во многих случаях пользователи могут согласиться с тем, что им необходимо перезапустить или обновить приложение, чтобы обновить нечасто обновляемые данные, особенно если оно может значительно сократить время отображения часто используемых элементов пользовательского интерфейса. Убедитесь, что вы понимаете реальное поведение уже развернутых элементов кэширования - многие распространенные методы кэширования (например, HTTP ETag) по-прежнему требуют обхода по сети для обеспечения согласованности, а там, где задержка в сети стоит дорого, вы можете избежать ее вообще с другой подход кеширования.
Распараллеливание : ищите последовательные транзакции, которые по логике не нужно выполнять строго последовательно, и переделывайте систему для их параллельной выдачи. Я имел дело с одним случаем, когда сквозной запрос имел внутреннюю сетевую задержку ~ 2 с, что не было проблемой для одной транзакции, но когда потребовалось 6 последовательных циклов 2 с, прежде чем пользователь восстановил контроль над клиентским приложением Это стало огромным источником разочарования. Обнаружение того, что эти транзакции на самом деле были независимыми, позволило им выполняться параллельно, уменьшая задержку для конечного пользователя до очень близкой к стоимости одного туда-обратно.
Объединение : если последовательные запросы должны выполняться последовательно, ищите возможности объединить их в один более полный запрос. Типичные примеры включают создание новых сущностей, за которыми следуют запросы связать эти сущности с другими существующими сущностями.
Сжатие : ищите возможности использовать сжатие полезной нагрузки, либо заменяя текстовую форму на двоичную, либо используя реальную технологию сжатия. Многие современные (т.е. в течение десятилетия) технологические стеки поддерживают это почти прозрачно, поэтому убедитесь, что он настроен. Я часто удивлялся значительному влиянию сжатия, когда казалось очевидным, что проблема заключалась, главным образом, в задержке, а не в пропускной способности, обнаруживая после того факта, что она позволяла транзакции помещаться в одном пакете или иным образом избегать потери пакетов и, следовательно, иметь большой размер влияние на производительность.
Повторите : вернитесь к началу и проведите повторную оценку ваших операций (в тех же местах и времени) с улучшениями на месте, запишите и сообщите свои результаты. Как и при любой оптимизации, некоторые проблемы, возможно, были решены, разоблачая другие, которые сейчас доминируют.
В описанных выше шагах я сосредоточусь на процессе оптимизации, связанном с приложением, но, конечно, вы должны убедиться, что базовая сеть настроена наиболее эффективным образом для поддержки вашего приложения. Привлеките сетевых специалистов к работе и определите, могут ли они применить улучшения емкости, QoS, сжатие сети или другие методы для решения проблемы. Как правило, они не понимают потребностей вашего приложения, поэтому важно, чтобы вы (после этапа анализа) имели возможность обсудить его с ними, а также обосновать любые расходы, которые вы собираетесь просить их понести. , Я сталкивался со случаями, когда неправильная конфигурация сети приводила к тому, что данные приложений передавались по медленной спутниковой линии связи, а не по наземной линии связи, просто потому, что он использовал порт TCP, который не был «хорошо известен» специалистам по сетевым технологиям; Очевидно, что устранение подобной проблемы может оказать существенное влияние на производительность, при этом не требуется никакого программного кода или изменений конфигурации.
источник
Очень сложно дать общий ответ на этот вопрос. Это действительно зависит от вашей проблемной области и технической реализации. Общий метод, который не зависит от языка: выявляйте горячие точки кода, которые нельзя устранить, и оптимизируйте код ассемблера вручную.
источник
Последние несколько% очень сильно зависят от процессора и приложения ....
Список можно продолжить .... Но такого рода вещи действительно являются последним средством ...
Сборка для x86 и запуск Valgrind / Cachegrind для кода для правильного профилирования производительности. Или CCStudio от Texas Instruments имеет приятный профиль . Тогда вы действительно будете знать, на чем сосредоточиться ...
источник
Did you know that a CAT6 cable is capable of 10x better shielding off extrenal inteferences than a default Cat5e UTP cable?
Для любых не автономных проектов, при наличии лучшего программного обеспечения и лучшего оборудования, если ваша пропускная способность слабая, эта тонкая линия будет сжимать данные и давать вам задержки, хотя и в миллисекундах ... но если вы говорите о последних падениях Это несколько полученных капель, 24/7 для любого отправленного или полученного пакета.
источник
Не так глубоко или сложно, как предыдущие ответы, но здесь: (это более начальный / средний уровень)
источник
Невозможно сказать. Это зависит от того, как выглядит код. Если мы можем предположить, что код уже существует, тогда мы можем просто посмотреть на него и выяснить, как его оптимизировать.
Лучшая локальность кэша, развертывание цикла, попытаться устранить длинные цепочки зависимостей, чтобы получить лучший параллелизм на уровне команд. Предпочитаю условные перемещения по веткам, когда это возможно. Используйте инструкции SIMD, когда это возможно.
Понять, что делает ваш код, и понять оборудование, на котором он работает. Тогда становится довольно просто определить, что вам нужно сделать, чтобы улучшить производительность вашего кода. Это действительно единственный по-настоящему общий совет, который я могу придумать.
Что ж, и «покажите код на SO и попросите совета по оптимизации для этого конкретного куска кода».
источник
Если лучше аппаратное обеспечение, то обязательно сделайте это. В противном случае
источник
Путь Google - это один из вариантов: «Кэшируйте его. По возможности, не трогайте диск».
источник
Вот несколько быстрых и грязных методов оптимизации, которые я использую. Я считаю, что это оптимизация «первого прохода».
Узнайте, на что тратится время Узнайте, что именно занимает время. Это файл IO? Это процессорное время? Это сеть? Это база данных? Оптимизировать для IO бесполезно, если это не узкое место.
Знайте свою среду Знание того, где оптимизировать, обычно зависит от среды разработки. Например, в VB6 передача по ссылке медленнее, чем передача по значению, но в C и C ++ по ссылке значительно быстрее. В C разумно попробовать что-то и сделать что-то другое, если код возврата указывает на сбой, в то время как в Dot Net перехват исключений происходит намного медленнее, чем проверка действительного условия перед попыткой.
Индексы Построить индексы для часто запрашиваемых полей базы данных. Вы почти всегда можете обменять пространство на скорость.
Избегайте поиска Внутри цикла, который нужно оптимизировать, я избегаю каких-либо поисков. Найти смещение и / или индекс вне цикла и повторно использовать данные внутри.
Сведите к минимуму количество попыток ввода-вывода, чтобы уменьшить количество раз чтения или записи, особенно по сетевому соединению.
Сокращение абстракций Чем больше уровней абстракции, через которые должен работать код, тем медленнее он. Внутри критического цикла уменьшите абстракции (например, откройте методы более низкого уровня, которые избегают лишнего кода)
Spawn Тема для проектов с пользовательским интерфейсом, порождая новую нить преформ медленнее задачи делает приложение чувствовать себя более отзывчивой, хотя и не является.
Предварительная обработка Обычно вы можете обменять пространство на скорость. Если есть расчеты или другие интенсивные операции, посмотрите, можете ли вы предварительно вычислить некоторую информацию до того, как попадете в критический цикл.
источник
Если у вас много высокопараллельных математических вычислений с плавающей запятой, особенно с одинарной точностью, попробуйте разгрузить его на графический процессор (если он есть) с помощью OpenCL или (для чипов NVidia) CUDA. Графические процессоры обладают огромной вычислительной мощностью с плавающей запятой в своих шейдерах, которая намного выше, чем у процессоров.
источник
Добавление этого ответа, так как я не видел его во всех остальных.
Минимизируйте неявное преобразование между типами и знаком:
Это относится, по крайней мере, к C / C ++. Даже если вы уже думаете, что у вас нет преобразований - иногда полезно проверить добавление предупреждений компилятора вокруг функций, которые требуют производительности, особенно для отслеживания преобразований внутри циклов.
GCC в частности: вы можете проверить это, добавив несколько подробных прагм вокруг вашего кода,
Я видел случаи, когда вы могли бы получить ускорение на несколько процентов, уменьшив количество конверсий, создаваемых такими предупреждениями.
В некоторых случаях у меня есть заголовок со строгими предупреждениями, которые я постоянно включаю, чтобы предотвратить случайные преобразования, однако это компромисс, поскольку вы можете в конечном итоге добавить много приведений к тихим намеренным преобразованиям, которые могут просто сделать код более загроможденным для минимального прибыли.
источник
Иногда может помочь изменение макета ваших данных. В C вы можете переключаться с массива или структур на структуру массивов или наоборот.
источник
Твик ОС и фреймворк.
Это может показаться излишним, но думать об этом так: операционные системы и фреймворки предназначены для многих вещей. Ваше приложение делает только очень конкретные вещи. Если бы вы могли заставить ОС делать именно то, что нужно вашему приложению, и чтобы ваше приложение понимало, как работает фреймворк (php, .net, java), вы могли бы намного лучше использовать свое оборудование.
Например, Facebook изменил некоторые вещи на уровне ядра в Linux, изменил работу memcached (например, они написали прокси memcached и использовали udp вместо tcp ).
Другой пример этого - Window2008. Win2K8 имеет версию, в которой вы можете установить только базовую ОС, необходимую для запуска приложений X (например, Web-Apps, Server Apps). Это снижает значительную часть накладных расходов, которые ОС несет на выполнение процессов, и повышает производительность.
Конечно, вы всегда должны добавить больше оборудования в качестве первого шага ...
источник