GC с C # и C ++ в одном решении - PullRequest
14 голосов
/ 02 марта 2010

У меня есть решение, состоящее из нескольких проектов на C #. Он был написан на C # для быстрого запуска. Сбор мусора начинает становиться проблемой & mdash; мы наблюдаем около 100 мс задержек, которых мы хотели бы избежать.

Одна мысль заключалась в том, чтобы переписать его на C ++, проект за проектом. Но если вы объедините C # с неуправляемым C ++, будут ли потоки в проектах C ++ также заморожены сборщиками мусора?

UPDATE

Спасибо за ваши ответы. На самом деле это приложение, где 100 мс может быть значительным. Вероятно, это было плохое решение для его сборки в C #, но в то время было важно, чтобы он работал быстро и без проблем.

В данный момент мы используем мультимедийные таймеры Windows для запуска события каждые 5 мс. Мы видим около 100 мс пробелов, и мы проверили счетчики GC, что они всегда происходят во время сбора. Оптимизация включена; встроенный в режиме Release.

Ответы [ 7 ]

6 голосов
/ 02 марта 2010

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

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

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

Еще одна простая задача - поиск любых ArrayList, HashTable или подобных неуниверсальных коллекций в вашем коде, которые блокируют / распаковывают типы значений, что приводит к совершенно ненужному выделению кучи. Замените их на List<T>, Dictionary<TKey, TValue> и т. Д., Где это возможно (здесь я специально имею в виду коллекции типов значений, таких как int, double, long и т. Д.). Аналогично, обратите внимание на любые методы, которые вы можете вызывать, какие аргументы типа значения блока (или возвращаемые типы значений в штучной упаковке).

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

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

Rapid Addition использует Microsoft .NET 3.5 Framework для создания обработки с минимальной задержкой FIX и FAST

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

4 голосов
/ 02 марта 2010

Вы уверены, что эти задержки в 100 мс связаны с ГХ? Я бы ОЧЕНЬ убедился, что GC действительно ваша проблема, прежде чем тратить много времени, сил и денег на переписывание вещей в C ++. Объединение управляемого кода с неуправляемым кодом также создает свои собственные проблемы, так как вам приходится иметь дело с сортировкой между этими двумя контекстами. Это добавит собственную потерю производительности, и ваш чистый выигрыш, скорее всего, в итоге окажется равным нулю.

Я бы профилировал ваше приложение на C # и точно определил, откуда происходят ваши задержки в 100 мс. Этот инструмент может быть полезен:

Как: использовать CLR Profiler

Слово на ГК

Еще одно слово о .NET GC (или, собственно, о любом GC, если на то пошло). Об этом не так часто говорят, но он является критическим фактором для успешного написания кода с помощью GC: * ​​1013 *

Наличие сборщика мусора не означает, что вам не нужно думать об управлении памятью!

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

Следующая статья также должна быть полезной, так как в ней описывается фундаментальное поведение .NET GC (действует через .NET 3.5 ... вполне вероятно, что эта статья больше не является полностью действительной для .NET 4.0, поскольку некоторые критические изменения в его GC ... во-первых, ему больше не нужно блокировать потоки .NET во время сбора):

Сборка мусора: автоматическое управление памятью в Microsoft .NET Framework

4 голосов
/ 02 марта 2010

Во-первых, вы пытались что-то профилировать, чтобы посмотреть, сможете ли вы оптимизировать использование памяти? Хорошее место для начала - с CLR profiler (работает со всеми CLR до 3.5).

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

3 голосов
/ 02 марта 2010

CLR GC не приостанавливает потоки, выполняющие неуправляемый код во время сбора. Если собственный код вызывает управляемый код или возвращается к управляемому коду, то на него может влиять коллекция (как и любой другой управляемый код).

1 голос
/ 02 марта 2010

.NET 4.0 имеет то, что называется Фоновая сборка мусора , что отличается от Параллельная сборка мусора , что может быть причиной вашей проблемы. Джейсон Олсон говорит об этом с Карлом Франклином и Ричардом Кэмпбеллом о .NET Rocks Episode # 517 . Вы можете просмотреть стенограмму здесь . Это на странице 5.

Я не совсем уверен, решит ли ваша проблема простое обновление до 4.0 Framework, но я думаю, что стоит потратить на это время, прежде чем переписывать все на C ++.

1 голос
/ 02 марта 2010

Одна мысль заключалась в том, чтобы переписать его на C ++, проект за проектом. Но если вы объедините C # с неуправляемым C ++, будут ли потоки в проектах C ++ также заморожены сборщиками мусора?

Нет, если код C ++ работает в разных потоках. куча C ++ и управляемая куча - разные вещи.

С другой стороны, если ваш код C ++ выполняет много нового / удаления, вы все равно начнете видеть остановки выделения в коде C ++, когда куча будет фрагментирована. И эти киоски, вероятно, будут намного хуже, чем то, что вы видите в коде C #, потому что нет GC. Когда нужно очистить кучу, это происходит внутри вызова new или delete.

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

1 голос
/ 02 марта 2010

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

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

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