Подтвердить что ты не робот

Когда сбор мусора может быть быстрее, чем ручное управление памятью?

При каких обстоятельствах сбор мусора эффективнее ручного управления памятью? (Здесь руководство может означать использование malloc и бесплатно, как в C, или чистые методы RAII и интеллектуального указателя, популяризированные С++)

Мне нравится, как сборка мусора может устранить некоторую случайную сложность при написании программного обеспечения, но я был еще более доволен тем, как RAII и интеллектуальные указатели могут устранить эту сложность, а также работать с ресурсами, отличными от памяти, будучи детерминированными и обеспечивая гарантии производительности и будучи более эффективными в целом. Поэтому я подумал, что могу смело игнорировать сбор мусора. Тем не менее, я заметил, что люди говорят, что сбор мусора быстрее, чем жесткое управление ресурсами, используемое на С++, например, когда доступно много дополнительной памяти.

Итак, когда именно сбор мусора превосходит ручное управление памятью? Мне нравятся RAII и интеллектуальные указатели, но с удовольствием принимаю сборку мусора в качестве другого инструмента, если это быстрее.

4b9b3361

Ответ 1

Никогда, и я могу это доказать.

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

Во-вторых, предположим, что лучший алгоритм GC использует времена T0...Tn, чтобы решить, должно ли освобождение памяти i быть освобождено в определенный момент. Тогда общее число Σ(Ti)

Теперь существует эквивалентный алгоритм управления ручным управлением памятью, который использует один и тот же алгоритм GC, но учитывает только блоки памяти, которые были отмечены вручную для освобождения. Поэтому время работы Σ(δiTi) (при δi = 0, когда блок я не был освобожден, и = 1, когда он был).

Очевидно, Σ(δiTi) ≤ Σ(Ti): есть ручной алгоритм, который строго не хуже алгоритма GC.

Как это контрастирует с другими ответами?

  • "С RAII вам нужно освобождать каждый раз, когда вы выделяете". - Нет, это ошибочное предположение. Мы должны сравнивать либо сгруппированные, либо без пакета операции. GC будет намного хуже, если вы также выполняете GC-сессию каждый раз, когда что-то выходит из сферы действия.
  • "Улучшенная локальность" - ну, если вы не снижаете тот факт, что языки, отличные от GC, могут использовать стек гораздо чаще, и этот стек имеет отличную локальность ссылок.
  • "низкие коэффициенты утечек" - это полностью верно, но мы обсуждали производительность во время выполнения. (Кстати: хорошо указать, что это низкие, но отличные от нуля).

Ответ 2

Преимущества GC:

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

Недостатки GC:

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

Это безумие для перфоманса, GC без проблем обойдется в распределитель кучи. Конкурс китайских программистов по программированию между Рико Мариани и Раймондом Ченом часто цитируется, обзор здесь. Программа Raymond С++ в конечном итоге выиграла, но только после ее перезаписи несколько раз и отказалась от стандартной библиотеки С++.

Ответ 3

Существует один конкретный сценарий, в котором указатель GC намного быстрее, чем интеллектуальный указатель (указатель на подсчет ссылок), когда оба реализованы в традиционном С++ (т.е. не С++/CLR, поскольку у нас не будет такой же роскоши, как Compact память после Mark-Sweep, и мы пытаемся сравнить яблоки с яблоками здесь, насколько мы можем), предполагая, что GC использует один и тот же основной менеджер памяти кучи. Это когда время назначения объекта значительно перегружает время создания объекта.

Примеры включают сортировку, разворот массива и т.д.

См. здесь больше информации о моем тесте с каркасом GC, который я реализовал с использованием традиционных ссылок С++ и ссылок на ссылки. Результатом теста разворота массива был GcString, который был в 16,5 раз быстрее, чем ref counted.

Это можно отнести к мучительно медленной семантике блокировки шины в указателе с подсчетом ссылок (если вы не нацеливаете только однопоточные приложения, для обеспечения безопасности потоков необходимы блокировки). По моему опыту внедрения высокопроизводительного точного GC в традиционном С++, я могу сказать, что есть больше возможностей для оптимизации с помощью руководства GC vs 'manual' (в соответствии с определением ОП ручного управления) (т.е. Интеллектуальными указателями).