Создавая собственную функцию malloc?

Я читал, что некоторые игры переписывают свой собственный malloc, чтобы быть более эффективными. Я не понимаю, как это возможно в мире виртуальной памяти. Если я правильно помню, malloc фактически называет специфическую для ОС функцию, которая сопоставляет виртуальный адрес с реальным адресом с MMU. Итак, как может кто-то сделать свой собственный распределитель памяти и выделить реальную память, не вызывая фактическое время выполнения malloc?

Спасибо

Ответ 1

Конечно, можно написать распределитель более эффективным, чем обычный.

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

Дело в том, что много лет назад нам приходилось разрабатывать и кодировать подсистему связи (HDLC, X.25 и проприетарные слои) для встроенных систем. Тот факт, что мы знали, что максимальное распределение всегда будет меньше 128 байтов (или что-то в этом роде), означало, что нам вообще не приходилось вмешиваться в блоки с переменным размером. Каждое выделение было для 128 байтов независимо от того, сколько вы просили.

Конечно, если вы попросили больше, он вернул NULL.

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

Конечно, это был особый случай, но вы также найдете это для игр. Фактически, мы даже использовали это в системе общего назначения, где распределения ниже определенного порога получали фиксированный объем памяти из автономного заранее распределенного пула, выполненного таким же образом. Любые другие распределения (превышающие порог или если пул был полностью выделен) были отправлены на "реальный" malloc.

Ответ 2

Просто потому, что malloc() является стандартной функцией C, это не означает, что у вас самый низкий уровень доступа к системе памяти. Фактически, malloc(), вероятно, реализован с точки зрения функциональности операционной системы нижнего уровня. Это означает, что вы можете называть эти интерфейсы нижнего уровня. Они могут быть специфичными для ОС, но они могут позволить вам повысить производительность, чем вы могли бы получить от интерфейса malloc(). Если бы это было так, вы могли бы реализовать свою собственную систему распределения памяти по своему усмотрению и, возможно, быть еще более эффективными - оптимизируя алгоритм для характеристик размера и частоты выделений, которые вы собираетесь делать, например.

Ответ 3

В общем случае malloc вызовет функцию, специфичную для ОС, чтобы получить кучу памяти (по крайней мере одну страницу VM) и затем делит эту память на более мелкие куски по мере необходимости, чтобы вернуться к вызывающему абоненту malloc.

Библиотека malloc также будет иметь список (или списки) свободных блоков, поэтому часто может удовлетворить запрос, не запрашивая ОС для большей памяти. Определение количества различных размеров блоков для обработки, принятия решения о попытке объединить смежные свободные блоки и т.д. - это выбор, который должен выполнить разработчик библиотеки malloc.

Вы можете обойти библиотеку malloc и напрямую вызвать функцию "дать мне некоторую память" на уровне OS и выполнить собственное выделение/освобождение в памяти, которую вы получаете от ОС. Такие реализации, скорее всего, будут специфичными для ОС. Другой альтернативой является использование malloc для начальных распределений, но сохранение собственного кеша освобожденных объектов.

Ответ 4

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

Ответ 5

Если я правильно помню, malloc на самом деле вызывает специфическую для ОС функцию

Не совсем. Большинство аппаратных средств имеет размер страницы 4 КБ. Операционные системы обычно не раскрывают интерфейс распределения памяти, предлагающий что-либо меньшее, чем размер страницы (и выравнивание по странице).

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

Существует распространенное заблуждение, что, когда вы free что-то, оно немедленно возвращается в операционную систему. Хотя это иногда происходит (особенно для больших блоков памяти), обычно бывает, что память free d остается выделенной для процесса и затем может быть повторно использована позднее malloc s.

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

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

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

Посмотрите пулы памяти и obstacks.