Будет ли сборка мусора C быстрее, чем C ++? - PullRequest
6 голосов
/ 08 февраля 2009

Я довольно долго размышлял о том, как управлять памятью в моем следующем проекте. Который пишет DSL на C / C ++.

Это можно сделать любым из трех способов.

  1. Ссылка считается C или C ++.
  2. Мусор собрал C.
  3. В C ++ копирование классов и структур из стека в стек и управление строками отдельно с помощью некоторого GC.

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

Смежный побочный вопрос. Будет ли malloc / free медленнее, чем выделять большой кусок в начале программы и запускать поверх него собственный менеджер памяти? .NET, кажется, делает это. Но меня смущает, почему мы не можем рассчитывать на то, что ОС сделает эту работу лучше и быстрее, чем мы можем сделать сами.

Ответы [ 11 ]

8 голосов
/ 08 февраля 2009

Все зависит! Это довольно открытый вопрос. Для этого нужно эссе!

Эй .. вот кто-то, кто подготовил ранее:

http://lambda -the-ultimate.org / узел / 2552

http://www.hpl.hp.com/personal/Hans_Boehm/gc/issues.html

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

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

Есть ли у вас действительно жесткие требования для быстрой езды? Многие приложения DSL не нуждаются в сырой производительности. Я бы предложил пойти с тем, что проще всего кодировать. Вы могли бы потратить всю жизнь на написание систем управления памятью и заботы о том, что лучше.

4 голосов
/ 08 февраля 2009

Почему сборка мусора C будет быстрее, чем C ++? Единственными сборщиками мусора, доступными для C, являются довольно неэффективные вещи, больше предназначенные для устранения утечек памяти, чем для фактического улучшения качества вашего кода.

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

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

Кроме того, невозможно сказать. У языков нет скорости. Нет смысла спрашивать, какой язык быстрее. Это зависит от 1) конкретного кода, 2) компилятора, который его компилирует, и 3) системы, на которой он работает (как аппаратного, так и операционного).

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

Причина в том, что ОС должна найти свободный кусок памяти, в основном, следуя связанному списку всех областей свободной памяти. В .NET вызов new () - это не что иное, как перемещение указателя кучи на столько байтов, сколько требуется для выделения.

4 голосов
/ 08 февраля 2009

э-э ... Зависит от того, как вы напишите систему сбора мусора для вашего DSL. Ни C, ни C ++ не имеют встроенного средства сбора мусора, но могут использоваться для написания очень эффективного или очень неэффективного сборщика мусора. Кстати, писать такую ​​вещь - нетривиальная задача.

DSL часто пишутся на языках более высокого уровня, таких как Ruby или Python, в частности, потому что разработчик языка может использовать сборку мусора и другие возможности языка. C и C ++ отлично подходят для написания полноценных языков промышленного уровня, но вам, безусловно, нужно знать, что вы делаете для их использования - знание yacc и lex особенно полезно здесь, но хорошее понимание динамики управление памятью также важно, как вы говорите. Вы также можете проверить keykit , музыкальный DSL с открытым исходным кодом, написанный на C, если вам все еще нравится идея DSL на C / C ++.

3 голосов
/ 08 февраля 2009

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

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

1 голос
/ 08 февраля 2009

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

За документацией и доказательствами, подтверждающими эти утверждения, вы можете ознакомиться с информацией на веб-сайте Boehm, а также с несколькими документами Бена Цорна об измеренной стоимости консервативного сбора мусора.

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

Проблема C против C ++ является ортогональной, но GC определенно будет быстрее, чем подсчет ссылок, особенно если компилятор не поддерживает подсчет ссылок.

1 голос
/ 08 февраля 2009

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

так что - пойти на компромиссное решение (которое на самом деле чертовски хорошо):

Вы создаете свои собственные кучи, по одному для каждого размера объекта, который вы обычно выделяете (или 4-байтового, 8-байтового, 16-байтового, 32-байтового и т. Д.), А затем, когда вам нужен новый фрагмент памяти, вы получаете последний «блок» в соответствующей куче. Поскольку вы предварительно выделяете из этих куч, все, что вам нужно сделать при распределении, это захватить следующий свободный блок. Это работает лучше, чем стандартный распределитель, потому что вы счастливо тратите память - если вы хотите выделить 12 байтов, вы потеряете целый 16-байтовый блок из 16-байтовой кучи. Вы сохраняете растровое изображение использованных v свободных блоков, чтобы вы могли быстро распределить ресурсы, не тратя много памяти и не сокращая их.

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

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

КСТАТИ. Причина, по которой стандартные распределители работают медленно, заключается в том, что они стараются не тратить память - поэтому, если вы выделите 5 байтов, 7 байтов и 32 байта из стандартной кучи, они сохранят эти «границы». В следующий раз, когда вам нужно выделить, он пройдет через тех, кто ищет достаточно места, чтобы дать вам то, что вы просили. Это хорошо работает для систем с малым объемом памяти, но вам нужно только посмотреть, сколько памяти использует большинство приложений сегодня, чтобы увидеть, что системы GC идут другим путем, и попытаться распределить ресурсы как можно быстрее, не заботясь об объеме памяти. впустую.

1 голос
/ 08 февраля 2009

Смежный побочный вопрос. Будет ли malloc / free медленнее, чем выделять большой патрон в начале программы и запускать поверх него собственный менеджер памяти? .NET, кажется, делает это. Но меня смущает, почему мы не можем рассчитывать на то, что ОС сделает эту работу лучше и быстрее, чем мы можем сделать сами.

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

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

0 голосов
/ 08 февраля 2009

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

C / C ++ разработаны в среде, где программист управляет своей собственной памятью. Попытка дооснастить GC или пересчитать их может помочь некоторым, но вы обнаружите, что вы либо должны поставить под угрозу производительность GC (потому что у него нет никаких подсказок компилятора о том, где могут быть указатели), либо вы ' найду новые и увлекательные способы, которыми вы можете испортить счетчик ссылок или GC или что-то еще.

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

0 голосов
/ 08 февраля 2009

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

0 голосов
/ 08 февраля 2009

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

Язык программирования D - это язык для сборки мусора, совместимый с C ABI и частично совместимый с C ++. На этой странице показаны некоторые критерии производительности строк в C ++ и D.

...