The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]



"Доступна библиотека управления памятью jemalloc 5.3.1"
Вариант для распечатки  
Пред. тема | След. тема 
Форум Разговоры, обсуждение новостей
Изначальное сообщение [ Отслеживать ]

"Доступна библиотека управления памятью jemalloc 5.3.1"  +/
Сообщение от opennews (ok), 14-Апр-26, 15:06 
Спустя 4 года после публикации прошлого обновления доступен релиз библиотеки управления памятью jemalloc 5.3.1, предлагающей альтернативную реализацию функций malloc, оптимизированную для снижения фрагментации и работы на многопроцессорных системах. Для решения проблем с блокировками на многоядерных системах в jemalloc для каждого ядра CPU используется своя изолированная область распределения памяти, что позволяет добиться  линейной масштабируемости при росте числа потоков...

Подробнее: https://www.opennet.dev/opennews/art.shtml?num=65201

Ответить | Правка | Cообщить модератору

Оглавление

Сообщения [Сортировка по времени | RSS]


1. "Доступна библиотека управления памятью jemalloc 5.3.1"  +/
Сообщение от Жироватт (ok), 14-Апр-26, 15:06 
Я бы даже не стал шутить про "отставить разврат - закопать стюардессу! отставить разврат - откопать стюардессу", но реально, в чем профит использовать конкретно этот аллокатор?
Ответить | Правка | Наверх | Cообщить модератору

2. "-"  +/
Сообщение от Аноним (2), 14-Апр-26, 15:34 
для каждого ядра CPU используется своя изолированная область распределения памяти, что позволяет добиться линейной масштабируемости при росте числа потоков
Ответить | Правка | Наверх | Cообщить модератору

4. Скрыто модератором  –1 +/
Сообщение от Жироватт (ok), 14-Апр-26, 15:50 
Ответить | Правка | Наверх | Cообщить модератору

5. "-"  –2 +/
Сообщение от Аноним (5), 14-Апр-26, 16:37 
>своя изолированная область

А как же общий буфер, общее адресное пространство процесса?

Ответить | Правка | К родителю #2 | Наверх | Cообщить модератору

8. "-"  +/
Сообщение от Аноним (8), 14-Апр-26, 16:46 
Общее адресное пространство никуда не делось, но в многопоточной среде эффективнее выделять из thread-local арен.
Ответить | Правка | Наверх | Cообщить модератору

10. "-"  +/
Сообщение от Аноним (5), 14-Апр-26, 17:01 
>thread-local

это понятно. Значит ли это что есть изолированная общая область памяти в дополнение к поточным?

Ответить | Правка | Наверх | Cообщить модератору

18. "-"  +/
Сообщение от Аноним (18), 14-Апр-26, 20:18 
Нет.

Адресное пространство общее. Но мы внутри процесса принимаем конвенцию, что для каждого потока есть выделенная область памяти, из которой он аллоцирует. Ядро и MMU об этом "ничего не знают", адресное пространство общее, просто процесс, использующий данный аллокатор, так работает со своей памятью.

Ответить | Правка | Наверх | Cообщить модератору

19. "-"  +/
Сообщение от Аноним (8), 14-Апр-26, 20:26 
Там нет и не может быть ничего "изолированного". Память выделенная на thread-local арене доступна всем потокам, и освобождается из любого, просто при выделении мы меньше ходим в shared state и ждём на локах.

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

Ответить | Правка | К родителю #10 | Наверх | Cообщить модератору

25. "-"  +/
Сообщение от Аноним (5), 14-Апр-26, 23:27 
Спасибо. Вроде понятно. Понятое изложил ниже.
Ответить | Правка | Наверх | Cообщить модератору

22. "-"  +/
Сообщение от Аноним83 (?), 14-Апр-26, 20:56 
Нет.

Значит что за каждым потоком закреплён "пул памяти" откуда именно этот поток получает куски памяти при каждом malloc()/realloc()/calloc().
Когда другой поток для такой памяти делает free() - то это в звисимости от опций и реализации может быть какой то lockless механизм который кусок памяти помещает в очередь на освобождение в пул того потока из которого но выделено. И оно там висит пока поток не потрогает апи аллокатора.
"пул памяти" - нечто виртуальное, можешь считать что это некоторая структура, вероятно со списками и массивами. Типа как экземпляр класса на крестах.

В общем вариантов много как и что можно с этим делать чтобы потоки друг другу не мешались выделяя/свобождая память.

Ответить | Правка | К родителю #10 | Наверх | Cообщить модератору

24. "-"  +/
Сообщение от Аноним (5), 14-Апр-26, 23:26 
Понятно. При создание потока ему передается указатель на структуру, через которую управляющий jemalloc выделил ему память (вроде this). Для прозрачности его теневым образом можно передавать функциям *alloc из этого потока. Владельцем структуры, отвечающей за память потока, остается поток "родивший" этот поток. Использующий структуру может только пометить кусок на удаление (или автоматически помечается на выходе). В асме я встречал инструкции работающие с сегментными регистрами на x64 (это и защищает приватную память потока).
Для общей памяти должны быть, тогда, "статические" функции аллоцирования.  
Ответить | Правка | Наверх | Cообщить модератору

26. "-"  +/
Сообщение от Аноним (8), 14-Апр-26, 23:28 
Нет никакой "приватной памяти потока".
Ответить | Правка | Наверх | Cообщить модератору

28. "-"  +/
Сообщение от Аноним (5), 14-Апр-26, 23:36 
В асме встречаются обращения к ячейкам памяти через сегментный регистр на x64. Инструкции асма в потоке могут содержать сегментную адресацию. То что это используется - это точно.
Ответить | Правка | Наверх | Cообщить модератору

29. "-"  +/
Сообщение от Аноним (5), 14-Апр-26, 23:39 
Я дам этому потоку смещенную базу и он будет наращивать потребление относительно этой базы (фрейм вутри общей памяти). Сама база находится внутри общей памяти процесса (1-го потока).
Легко убрать просто переместив базу и удалив структуру (handle) потокового фрейма.
Ответить | Правка | К родителю #26 | Наверх | Cообщить модератору

30. "-"  +/
Сообщение от Аноним (5), 14-Апр-26, 23:44 
Возможно Вы мыслите в абстракциях. Я стараюсь мыслить в асм реализации.
Ответить | Правка | К родителю #26 | Наверх | Cообщить модератору

39. "-"  +/
Сообщение от Аноним (39), 15-Апр-26, 01:19 
> Я стараюсь мыслить в асм реализации.

Очень плохо, потому что x86 не единственная и уже даже не основная архитектура.

Ответить | Правка | Наверх | Cообщить модератору

27. "-"  +/
Сообщение от Аноним (5), 14-Апр-26, 23:30 
Тогда суть в том что упор делается на поточный пул и разнобой общей памяти от потоков уменьшается и защищается память потоков.Получается уменьшение "поточной" фрагментации. Значительные куски освобождаются по завершение конкретного потока.
Ответить | Правка | К родителю #24 | Наверх | Cообщить модератору

32. "-"  +/
Сообщение от Аноним83 (?), 15-Апр-26, 00:19 
Как то так так.

Есть TLS: Thread Local Storage.
Это как бы массив, когда ты туда хочешь что то записать ты аллоцируешь от туда индекс через pthread_key_create().
Дальше через апи каждый поток в этот индекс пишет pthread_setspecific(), и у каждого потока там своё уникальное значение может хранится. Те каждый поток дёргая pthread_getspecific() с этим аллоцированным индексом может получать то значение которое привязано к этому потоку.

Дальше там особенности аллокаторов, но в целом аллокаторы как провайдеры: берут оптом - продают в розницу. Выделают какие то большие куски через mmap(), и отдают по запросу из них маленькие кусочки. Выделить меньше PAGE_SIZE (4кб на х84) не возможно. Упомянутый dss - устарел, хз как он работал.

У каждого потока свои страницы из которых он получает память при alloc(), а если соседний поток эти куски освобождает то они через lockfree ставятся в очередь на освобождение, которая обрабатывается потоком к которому прибит "экземпляр" аллокатора.

Как там происходит на низком уровне в плане инита аллокатора на старте процесса и для новых потоков - я не в курсе. Скорее всего в либС есть код который дёргает аллокатор инит и тот как минимум делает pthread_key_create(). А дальше при первом обращении к АПИ аллокатора можно проверять что там из массива прочитался не NULL иначе делать инит экземпляра под поток. При завершении потока - хз, может где то хук есть в либС. Возможно в либС просто есть свой враппер для pthread_create() который подсовывает свою функцию, где есть код для инита и деинита экземпляра аллокатора привязанного к потоку.

Идея в том, чтобы потоки не тупили когда надо много мелких (мнее PAGE_SIZE) кусочков выделять/освобождать и ждали друг друга и не ходили к mmap всей толпой через одну дверь по одному.

Остальное лучше читать где то в литературе или исходниках.

Ответить | Правка | К родителю #24 | Наверх | Cообщить модератору

35. "-"  +/
Сообщение от Аноним (5), 15-Апр-26, 00:36 
> Есть TLS: Thread Local Storage.
> Это как бы массив, когда ты туда хочешь что то записать ты
> аллоцируешь от туда индекс через pthread_key_create().
> Дальше через апи каждый поток в этот индекс пишет pthread_setspecific(), и у
> каждого потока там своё уникальное значение может хранится. Те каждый поток
> дёргая pthread_getspecific() с этим аллоцированным индексом может получать то значение
> которое привязано к этому потоку.

pthread_key_create() - регистрируем ID1 первого потока у диспетчера.
pthread_setspecific() - регистрируем и получаем ID2 другого потока ссылаясь на ID1 первого как родителя
pthread_setspecific() - получаем указатель связанный с ID2 прилепленный диспетчером к уже полученным кускам этого потока.

Есть родитель ID1 он же владеет общим пулом. Есть ID2 который узнаваем диспетчером и получает новую память для себя впритык к уже имеющейся и легко освобождаемую большим куском.  

Ответить | Правка | Наверх | Cообщить модератору

37. "-"  +/
Сообщение от Аноним83 (?), 15-Апр-26, 01:05 
Нет.

static pthread_key_t tp_tls_key_tpt;
static int tp_tls_key_tpt_error = EAGAIN;

int tp_init(void) {
    if (0 != tp_tls_key_tpt_error) { /* Try to reinit TLS. */
        tp_tls_key_tpt_error = pthread_key_create(&tp_tls_key_tpt, NULL);
    }
    return (tp_tls_key_tpt_error);
}

static void *tp_thread_proc(void *data) {
...
    pthread_setspecific(tp_tls_key_tpt, (const void*)data);
...
// do something...
...
    pthread_setspecific(tp_tls_key_tpt, NULL);
    return (NULL);
}

void *tpt_get_current(void) { /* TLS magic. */
    return ((void*)pthread_getspecific(tp_tls_key_tpt));
}

Это чуть упрощённое из моего кода.
tp_init() вызывается типа один раз при старте.
Каждый поток в tp_thread_proc() получает свой какой то указатель на данные и сохраняет его в TLS.
Вызывая tpt_get_current() из любой функции в контексте выполнения такого потока можно получить указатель на данные (void *data) который передали при создании потока.
Прикол тут в том, что для всех потоков код который они вызывают и аргумент один и тот же а результат разный.

Ответить | Правка | Наверх | Cообщить модератору

31. "-"  +/
Сообщение от Аноним (5), 15-Апр-26, 00:01 
>за каждым потоком закреплён "пул памяти" откуда именно этот поток получает куски памяти при каждом malloc()/realloc()/calloc().

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

Ответить | Правка | К родителю #22 | Наверх | Cообщить модератору

33. "-"  +/
Сообщение от Аноним83 (?), 15-Апр-26, 00:25 
> malloc(xxx) вызывается на самом деле malloc(this_thread,xxx).

Может в какой то реализации так и есть, я таких не видел да и смысла не понимаю.
Аллокатор сильно сложнее устроен чем просто как вы описали, как минимум он обычно возвращает выравненную память по границе sizeof(void*). Потом ему нужно к каждому куску памяти клеить свои метаданные - обычно оно находится ПЕРЕД тем значением что вернули через malloc().

У вас какой то очень вырожденный юзкейс, в реале всё сложнее.

Ответить | Правка | Наверх | Cообщить модератору

36. "-"  +/
Сообщение от Аноним (5), 15-Апр-26, 00:41 
>> malloc(xxx) вызывается на самом деле malloc(this_thread,xxx).
> Может в какой то реализации так и есть, я таких не видел

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


Ответить | Правка | Наверх | Cообщить модератору

38. "-"  +/
Сообщение от Аноним83 (?), 15-Апр-26, 01:05 
Удачи в реализации.
Ответить | Правка | Наверх | Cообщить модератору

6. "-"  +/
Сообщение от Аноним (5), 14-Апр-26, 16:38 
Меньшая фрагментация за счет изолированных областей? А внутри области такая же дефрагментация?
Ответить | Правка | К родителю #2 | Наверх | Cообщить модератору

9. "-"  +/
Сообщение от Аноним (8), 14-Апр-26, 16:46 
> Меньшая фрагментация за счет изолированных областей?

Не фрагментация, а lock contention.

Ответить | Правка | Наверх | Cообщить модератору

11. "-"  +/
Сообщение от Аноним (5), 14-Апр-26, 17:03 
Прожорливый поток может залочить себе всю память?
Ответить | Правка | Наверх | Cообщить модератору

17. "-"  +/
Сообщение от Аноним (8), 14-Апр-26, 20:16 
Нет, потоки будут бороться за доступ к shared структурам аллокатора.
Ответить | Правка | Наверх | Cообщить модератору

7. "Доступна библиотека управления памятью jemalloc 5.3.1"  +2 +/
Сообщение от Аноним (8), 14-Апр-26, 16:44 
> в чем профит использовать конкретно этот аллокатор?

Он один из самых эффективных.

Ответить | Правка | К родителю #1 | Наверх | Cообщить модератору

14. "Доступна библиотека управления памятью jemalloc 5.3.1"  +/
Сообщение от Аноним (14), 14-Апр-26, 17:50 
> в чем профит использовать конкретно этот аллокатор?
> месяц назад разработку возобновила компания Meta, применяющая jemalloc в своей инфраструктуре

Это не тут спрашивать надо, это на https://engineering.fb.com спрашивать надо.

Ответить | Правка | К родителю #1 | Наверх | Cообщить модератору

23. "Доступна библиотека управления памятью jemalloc 5.3.1"  +/
Сообщение от Noname (??), 14-Апр-26, 21:10 
Naprimer dlya mysql/mariadb
https://www.mydbops.com/blog/troubleshooting-mariadb-memory-...
Ответить | Правка | К родителю #1 | Наверх | Cообщить модератору

12. "Доступна библиотека управления памятью jemalloc 5.3.1"  +/
Сообщение от Аноним (12), 14-Апр-26, 17:07 
Кстати, раз речь пошла о аллокаторах, что использовать вместе с musl? Сабж или в интернете ещё другие нахваливают?
Ответить | Правка | Наверх | Cообщить модератору

15. "Доступна библиотека управления памятью jemalloc 5.3.1"  –2 +/
Сообщение от Аноним (15), 14-Апр-26, 17:51 
> вместе с musl

* Вместо musl.

Glibc.

Ответить | Правка | Наверх | Cообщить модератору

16. "Доступна библиотека управления памятью jemalloc 5.3.1"  –1 +/
Сообщение от Аноним (16), 14-Апр-26, 18:38 
странный вопрос, есть "стандарт", который по сути есть компромис среди множества архитектур и альтернатив аля glibc, то есть работает не идеально, но приемлемо, чего достаточно для большенства задач, но если вам не достаточно, то надо отталкиваться от архитектуры и особенностей проекта, можно попробовать для начала и сабж, но musl скорее про эндебер и там будет скорее хуже, а значит писать свое под свою задачу, хотя, если проект один, проще это решать на уровне проекта чтобы не плодить сущности. Резервировать кусок памяти и в нем уже чтото делать, создавать обьекты и удалять не возвращая память системе, тем самым избавившись от всяких дабл-фри бай дизайн, это сложный путь, но один раз его пройдя можно попутно решить все "проблемы", в том числе с выходом за границы буфера, юз-афтер-фри, и прочие за которые хейтят сечас си, и восхваляют раст, в котором это гвоздями прибито, и никаких шагов влево вправо не дозволяется.
Ответить | Правка | К родителю #12 | Наверх | Cообщить модератору

20. "Доступна библиотека управления памятью jemalloc 5.3.1"  +1 +/
Сообщение от Аноним (8), 14-Апр-26, 20:42 
> Резервировать кусок памяти и в нем уже чтото делать, создавать обьекты и удалять не возвращая память системе, тем самым избавившись от всяких дабл-фри бай дизайн, это сложный путь

А чего сложного? Сделать no-op free() совсем несложно.

> но один раз его пройдя можно попутно решить все "проблемы"

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

> в том числе с выходом за границы буфера

Double free и use after free, допустим, действительно решим, отказавшись от free. Но интересно, как это поможет от выхода за границы буфера?

> и восхваляют раст, в котором это гвоздями прибито, и никаких шагов влево вправо не дозволяется.

В rust, который ты, конечно, в глаза не видел, ничего гвоздями не прибито. Там есть и упомянутые bump аллокаторы, которые можно использовать как глобально так и по месту, и контролируемую утечку памяти можно устроить даже без unsafe, превратив любое динамически выделенное значение в &'static, а машинерии для жонглирования слайсами там столько что скоро его за перегруженность как плюсы будут ругать. Но DF/UAF на ровном месте, действительно, не сделать. Расскажи, почему это плохо.

Ответить | Правка | Наверх | Cообщить модератору

21. "Доступна библиотека управления памятью jemalloc 5.3.1"  +/
Сообщение от Аноним83 (?), 14-Апр-26, 20:52 
--disable-dss - это уже давным давно было.
В остальном больше гонева было что оно там самосгнило без свежих коммитов.
Ответить | Правка | Наверх | Cообщить модератору

Архив | Удалить

Рекомендовать для помещения в FAQ | Индекс форумов | Темы | Пред. тема | След. тема




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2026 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру