Что нужно делать в управляемом коде, чтобы сохранить хорошую производительность? - PullRequest
7 голосов
/ 08 января 2012

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

(Примечание: пожалуйста, не жалуйтесь на код, который сам не написал, такой как STL, это неуправляемый код на C ++в конце концов, это важная часть).

Но в управляемом коде, таком как код в Java и C #, вы не контролируете каждый процесс, а память «скрыта» или не находится под вашим контролем,в некоторой степени.И это делает производительность чем-то относительно неизвестным, в основном вы боитесь плохой производительности.

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

Я мог бы подумать только о некоторых практиках, таких как:

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

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

Обратите внимание, что я не прошу сравнивать код C ++ VS C # (или Java), я просто упомянул C ++, чтобы объяснить проблему.

Ответы [ 6 ]

5 голосов
/ 08 января 2012

Здесь нет однозначного ответа.Единственный способ ответить на это: профиль.Измеряйте рано и часто.Узкие места обычно не там, где вы их ожидаете.Оптимизируйте вещи, которые на самом деле причиняют боль.Для этого мы используем mvc-mini-profiler, но любой аналогичный инструмент будет работать.

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

Очевидно, что внешние ресурсы будут медленными;кэширование может быть критическим: в нечетных сценариях с очень долгоживущими данными есть приемы, которые вы можете сделать со структурами, чтобы избежать длинных сборов GEN-2;Сериализация (файлы, сеть и т. д.), материализация (ORM) или просто неверный выбор коллекции / алгоритма могут быть самой большой проблемой - вы не можете знать, пока не измерите.


Двахотя:

  • убедитесь, что вы понимаете, что значит IDisposable и "использование"
  • не объединяет строки в циклах;массовая конкатенация - это работа StringBuilder
4 голосов
/ 08 января 2012

Повторное использование больших объектов очень важно в моем опыте.

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

1 голос
/ 08 января 2012

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

Например, по умолчанию JVM , которую использует большинство людей, - виртуальная машина Sun Hotspot , которая фактически оптимизирует ваш код во время его работы путем преобразования частей программы в собственный код, включая fly и другие оптимизации (такие как CLR или другие управляемые среды выполнения), которые вы никогда не получите, используя C ++. Кроме того, Hotspot также определит, какие части вашего кода используются чаще всего, и оптимизирует их соответствующим образом. Итак, как вы можете видеть, оптимизировать производительность в управляемой системе немного сложнее, чем в неуправляемой системе, потому что у вас есть промежуточный уровень, который может сделать код быстрее без вашего вмешательства.

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

0 голосов
/ 27 июня 2012

Вы должны: использование больших объектов очень важно в моем опыте.

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

0 голосов
/ 08 января 2012

.NET Generics не специализируется на ссылочных типах, что серьезно ограничивает объемы встраивания. В определенных точках производительности может иметь смысл отказаться от универсального типа контейнера в пользу конкретной реализации, которая будет лучше оптимизирована. (Примечание: это не означает использование контейнеров .NET 1.x с типом элемента object).

0 голосов
/ 08 января 2012

Я бы предложил лучше понять сборщик мусора алгоритмы.Вы можете найти хорошие книги по этому вопросу, например, Справочник по сборке мусора (Ричард Джонс, Энтони Хоскинг, Элиот Мосс).

Тогда ваш вопрос практически связан с конкретной реализацией, ивозможно даже к определенной версии этого.Например, Mono использовал (например, в версии 2.4) для использования сборщика мусора Boehm, но теперь использует копирующий поколенческий.

И не забывайте, что некоторыеМетоды ГХ могут быть удивительно эффективными.Вспомните старую статью A.Appel Сборка мусора может быть быстрее, чем выделение стека (но сегодня производительность кэша имеет гораздо большее значение, поэтому детали различаются).

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

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

И некоторые реализации GC довольно быстрые.Например, тот, что внутри Ocaml

Я бы не стал так сильно беспокоиться: преждевременная оптимизация - это зло.

(и управление памятью в C ++, даже с помощью интеллектуальных указателей или с ref-счетчики, часто можно рассматривать как технику сбора мусора бедного человека, и вы не имеете полного контроля над тем, что делает C ++, - если вы не реализуете свой ::operator new, используя системные вызовы операционной системы, - так что вы нене знаю, априори его производительность)

...