LINUX.ORG.RU

Когда нужен свой аллокатор в C++?

 ,


0

1

// Тема переименована из «Почему в C++ каждый проект пишет свой аллокатор?»

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



Последнее исправление: Original_1 (всего исправлений: 1)

Почему в C++ каждый проект пишет свой аллокатор?

Хороший аллокатор для нынешней архитектуре объектов никто не разработает.

В лучшем случае лишь некая оптимизация для оптимального использования базовых типов данных.

То бишь списки для: 1, 2, 4, 8, 16, ... ,блоков данных.

Безусловно такой подход много лучше чем использования памяти по типу «куча мала».

Forum0888
()

Почему в C++ каждый проект пишет свой аллокатор?

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

alysnix ★★★
()

Потому что программы по разному получают освобождают память, одни получают/отдают всегда фиксированное значение, другие наоборот всегда разное, но в неких рамках, третьи половину памяти берут/отдают большими кусками, а половину маленькими. И у всех, аллокация/реалокация происходит часто. Ну и не прям уж каждый, свой аллокатор писать это когда у тебя уже всё остальное вылизано доблеску, ну или по приколу.

LINUX-ORG-RU ★★★★★
()
Последнее исправление: LINUX-ORG-RU (всего исправлений: 1)

Свои аллокаторы имеют только старые и крупные проекты.

А до появления pmr с аллокаторами в плюсах творилось нечто странное. Как следствие людям приходилось писать своё, это своё расползлось по проекту и сейчас с него слезть практически невозможно. Ну и разумеется, любой быстрый аллокатор будет чудовищно медленным в другом сценарии использования. Алгоритм может быть либо очень быстрым, но только в одном сценарии использования, либо везде не очень медленным (ну или всегда плохим, конечно). Собственно последние и попадают в стандартную библиотеку и т.п.

Короче всё как со строками, только с аллокаторами.

Ivan_qrt ★★★★★
()
Ответ на: комментарий от annulen

Люди даже не могут придумать универсальный класс для работы со строками

Ну почему же? Вот в Qt вполне себе универсальный класс для работы со строками.

rumgot ★★★★★
()

Комментарий про коньяк по утрам уже был? Был, вижу, это хорошо.

Нет, в заголовке 4.2, свой аллокатор пишет не каждый проект, а только те, которые уткнулись в неоптимальность стандартного. Зачем — выше примерно объяснили.

hobbit ★★★★★
()
Ответ на: комментарий от AntonI

аналогично. Для фортрана коллеги писали свой менеджер памяти, но это было ещё в ту далёкую пору, когда только-только начали переходить от f77 к f90…

vasilisk_lo
()
Последнее исправление: vasilisk_lo (всего исправлений: 1)

Индустрия удивляет!

Хотя бы разработали оптимальные алгоритмы для работы с строками.
Ведь то, что ныне имеем - ЛАБА.

Да и архитектура Unicode ведь «не очень».

Forum0888
()
Ответ на: комментарий от her_s_gory

Статический массив будет маленький.

@x22

mmap()

Почти те же яйца что и malloc, только в профиль?

@DumLemming

Мегаструктуру фигачишь и всё

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

AntonI ★★★★
()

Помнится, когда Firefox перешёл на jemalloc, мем про наглую рыжую и толстую морду, жрущую RAM исчез и Firefox с jemalloc действительно ощутимо меньше стал кушать.

EXL ★★★★★
()
Ответ на: комментарий от AntonI

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

Если подробнее, то рассказ нужно начать с ассемблера. Не очень глубоко. Вы кодили когда-нибудь на ассемблере? Помните из каких секций, сегментов состоит программа? Помните такой сегмент данных?

Так вот, когда программа загружена в память, то место куда она загружена – это и есть сегмент данных, на х86. Примерно сразу после вашего кода – этот сегмент данных заканчивается и начинается стек. Т.е. здесь проходит граница сегмента данных и стека. Собственно, это все. А где же куча?

Стек спускается сверху вниз. И до границы дата-сегмента данные в стеке могут никогда не дойти. Там очень много. 4 гигабайта – полное пространство, а на стек это минус размер дата-сегмента т.е. минус ваш код пока что.

Значит, можно подвинуть границу стека вверх. От него не убудет. Тем самым мы увеличим дата-сегмент. Вот собственно этим и занимается ядро. Вот об этом можно его попросить.

Окей, подвинули мы границу. У нас теперь есть пространство после нашего кода. Вот это и есть та самая куча. И выделение в ней куска на самом деле сводится к разметке Т.е. маллок должен так вести учет этого свободного пространства, чтобы достаточно быстро находить «свободное» место нужного размера для ваших нужд.

Понятно?

hibou ★★★★★
()
Последнее исправление: hibou (всего исправлений: 1)

Во-первых, далеко не каждый проект. Выделение памяти далеко не всегда узкое место. А преждевременная оптимизация плохо.

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

В-третьих, бывает, что ты работаешь со специфическим классом объектов. Например, много объектов одного размера (эффективно держать их пул, а не выделять по одному в куче). Или тебе может быть нужна сборка мусора (например, ты пишешь свой скриптовой ЯП). Тогда обычные аллокации ты делаешь обычным аллокатором, а особые аллокации своим аллокатором.

Короче, сильно зависит от задачи. И в общем случае свой аллокатор не пишут, только в частном.

KivApple ★★★★★
()
Последнее исправление: KivApple (всего исправлений: 2)
Ответ на: комментарий от Kosyak

Хорошо, но без основ всё равно никуда. Тут надо еще разобраться из чего состоит адресное пространство процесса и куда ядро мапит эти страницы. И может ли быть это пространство больше 4 гигабайт сейчас суммарно.

hibou ★★★★★
()
Ответ на: комментарий от hibou

Т.е. важно понимать, что обещанное пространство не значит реальное. То, что процессу на старте обещано 4 гига – это не значит, что прям реально дали. Не означает, что адреса после дата-сегмента реально соответствуют каким-то страницам в памяти. Хотя казалось бы это стек.

Понятно, что ядро знает сколько данных лежит в стеке и не станет выделять на него честные страницы прям до формальной границы. Это не зачем. Когда понадобятся – выделит, если сможет.

hibou ★★★★★
()
Ответ на: комментарий от hibou

Если знаешь что-то насчет этого

Пару вещей слышал когда-то…

Зачем все эти ухмылки, ужимки?

Просто подкидываю пищу для размышлений, чтобы не было «а стек мы задвинем в самый конец адресного пространства». Кстати, а где оно в 64битах?

bugfixer ★★★★★
()
Ответ на: комментарий от hibou

Еще, кстати, забыты динамические библиотеки, которые тоже мапятся куда-то туда. Куда?

Так что, обо всех нюансах не упомнишь. Да и мы тут не книгу пишем.

hibou ★★★★★
()

О, когда этот момент настанет - ты поймёшь :)

Но почему тогда не сделали какой-нибудь стандартизированный быстрый аллокатор?

Сделали, ну разве что не стандартизированный, но в каждой реализации стандартной библиотеки достаточно эффективный аллокатор, с аренами, блэкджеком и нужным уровнем надёжности для общего случая.

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

faq2
()

Потому что в разных ситуациях разные аллокаторы оказываются эффективнее. Например - есть у тебя постоянный поток короткоживущих объектов, то делать на каждый чих malloc/free дорого. Проще сообразить arena allocator, ну или object pool по ситуации.

Ну и если NUMA начинается - там мрак и содомия.

Dark_SavanT ★★★★★
()