performance - увеличить - что быстрее java или c#




Стратегии оптимизации производительности в крайнем случае (20)

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

Предположим:

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

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

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

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


Бросьте больше аппаратного обеспечения!


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

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

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


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

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

Несколько примеров:

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

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


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

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

Никогда не используйте select *, только возвращайте нужные вам поля. Это особенно верно, если есть какие-либо соединения, поскольку поля объединения будут повторяться и, таким образом, вызывают ненужную нагрузку как на сервере, так и на сети.

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

Индекс, индекс, индекс. И обновите эту статистику, если это применимо к вашей базе данных.

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

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

Никогда не помещайте петлю любого типа в триггер!

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

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

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

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


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

  • ... если это память - найдите одну из книг, написанных много лет назад Кнутом, одним из сериалов «Искусство программирования». Скорее всего, речь идет о сортировке и поиске - если моя память ошибочна, вам придется выяснить, в чем он говорит о том, как справляться с медленным хранением данных на ленте. Мысленно преобразуем его пару памяти / ленты в пару кэш / основную память (или в пару кеша L1 / L2) соответственно. Изучите все трюки, которые он описывает, - если вы не нашли что-то, что решает вашу проблему, тогда нанять профессионального компьютерного ученого для проведения профессиональных исследований. Если ваша проблема с памятью случайно связана с FFT (промахи в кешах при индексированных по битам индексах при создании бабочек radix-2), то не нанимайте ученого - вместо этого ручная оптимизация проходит один за другим, пока вы не выиграете или не получите к тупику. Вы упомянули о том, чтобы выжать до последних нескольких процентов ? Если это немного, вы, скорее всего, победите.

  • ... если это процессор - переключитесь на язык ассемблера. Спецификация процессора исследования - что требует тиков , VLIW, SIMD. Функциональные вызовы, скорее всего, являются сменными клещами. Изучите преобразования циклов - конвейер, разворот. Умножения и деления могут быть сменными / интерполированными с битовыми сдвигами (умножения на малые целые числа могут быть заменены добавками). Попробуйте трюки с более короткими данными - если вам повезет, одна инструкция с 64 битами может оказаться заменой двумя на 32 или даже 4 на 16 или 8 на 8 бит. Попробуйте также более длинные данные - например, ваши вычисления с плавающей точкой могут оказаться более медленными, чем двойные, на конкретном процессоре. Если у вас есть тригонометрический материал, сражайтесь с заранее рассчитанными таблицами; также помните, что синус малой величины может быть заменен этим значением, если потеря точности находится в допустимых пределах.

  • ... если это сеть - подумайте о сжатии данных, которые вы передаете. Замените передачу XML двоичным. Протоколы обучения. Попробуйте UDP вместо TCP, если вы можете каким-то образом обработать потерю данных.

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

HTH :)


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

Это те эффекты, которые вам нужны для управления. Иногда через микро управление вашим кодом, но иногда через тщательное рассмотрение и рефакторинг.

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

  • Избегайте задержек памяти.
  • Уменьшение давления в шине памяти (полоса пропускания).

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

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

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


Хотя мне нравится ответ Майка Данлэйви, на самом деле это отличный ответ на примере поддержки, я думаю, что это можно было бы выразить очень просто:

Узнайте, что занимает наибольшее количество времени, и поймите, почему.

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

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

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

HPH, asoudmove.


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

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

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


Did you know that a CAT6 cable is capable of 10x better shielding off extrenal inteferences than a default Cat5e UTP cable?

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


Измените ОС и структуру.

Это может показаться излишним, но подумайте об этом следующим образом: операционные системы и Frameworks предназначены для выполнения многих задач. Ваше приложение выполняет только конкретные вещи. Если бы вы могли заставить ОС делать то, что нужно вашему приложению, и чтобы ваше приложение понимало, как работает фреймворк (php, .net, java), вы можете получить гораздо больше средств от своего оборудования.

Facebook, например, изменил некоторые вещи уровня ядра в Linux, изменил работу memcached (например, они написали прокси-сервер memcached и использовали udp вместо tcp ).

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

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


Разделите и победите

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


Уменьшить размеры переменных (во встроенных системах)

Если размер переменной превышает размер слова в определенной архитектуре, это может существенно повлиять на размер и скорость кода. Например, если у вас 16-разрядная система и long intчасто использую переменную, а потом понимаем, что она никогда не может выйти за пределы диапазона (-32.768 ... 32.767), подумайте о ее сокращении доshort int.

По моему личному опыту, если программа готова или почти готова, но мы понимаем, что она занимает около 110% или 120% программной памяти целевого оборудования, быстрая нормализация переменных обычно решает проблему чаще, чем нет.

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

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

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


Последние несколько% - это очень важная вещь для процессора и приложений ....

  • кеш-архитектуры отличаются, некоторые чипы имеют встроенную оперативную память, которую вы можете отображать напрямую, ARM (иногда) имеют векторный блок, SH4 - полезный код операции матрицы. Есть ли GPU - возможно, шейдер - это путь. TMS320 очень чувствительны к ветвям внутри циклов (поэтому отдельные петли и, если возможно, перемещают внешние условия).

Список продолжается ... Но эти вещи действительно являются последним средством ...

Создайте для x86 и запустите Valgrind / Cachegrind против кода для правильного профилирования производительности. Или у CCStudio Texas Instruments есть сладкий профилировщик. Тогда вы действительно будете знать, где сосредоточиться ...


Путь google - это один из вариантов «Cache it .. По возможности не касайтесь диска»


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


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

Узнайте, где потрачено время. Узнайте, что именно занимает время. Это файл IO? Это время процессора? Это сеть? Это база данных? Бесполезно оптимизировать IO, если это не узкое место.

Знать свою среду Знать, где оптимизировать, как правило, зависит от среды разработки. Например, в VB6 передача по ссылке медленнее, чем передача по значению, но в C и C ++ ссылочная ссылка значительно быстрее. В C, разумно попробовать что-то и сделать что-то другое, если код возврата указывает на сбой, а в Dot Net исключения catching намного медленнее, чем проверка действительного состояния перед попыткой.

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

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

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

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

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

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


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


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

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

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

Ну, и «Покажите код на SO и попросите совета по оптимизации для этой конкретной части кода».


  • Встроенные процедуры (исключить вызов / возврат и нажатие параметров)
  • Попробуйте исключить тесты / переключатели с помощью табличного поиска (если они быстрее)
  • Развернуть петли (устройство Даффа) до точки, где они просто вписываются в кеш процессора
  • Локализовать доступ к памяти, чтобы не взорвать кеш
  • Локализовать связанные вычисления, если оптимизатор еще не делает этого
  • Устраните инварианты цикла, если оптимизатор еще не делает этого

  • Когда вы доберетесь до того, что используете эффективные алгоритмы, это вопрос о том, что вам нужно больше скорости или памяти . Используйте кеширование для «оплаты» в памяти для большей скорости или использования вычислений для уменьшения объема памяти.
  • Если возможно (и более экономически выгодно) бросать аппаратные средства в проблему - быстрее процессор, больше памяти или HD может решить проблему быстрее, чем пытаться ее кодировать.
  • Если возможно, используйте распараллеливание - выполните часть кода на нескольких потоках.
  • Используйте правильный инструмент для работы . некоторые языки программирования создают более эффективный код, используя управляемый код (например, Java / .NET), ускоряют разработку, но собственные языки программирования создают более быстрый запуск кода.
  • Микро оптимизация . Только применимые вы можете использовать оптимизированную сборку для ускорения небольших фрагментов кода, использование оптимизаций SSE / vector в правильных местах может значительно повысить производительность.




language-agnostic