накладные расходы для пустой динамической арены

Моими инструментами являются Linux, gcc и pthreads. Когда моя программа вызывает new/delete из нескольких потоков и когда возникает конкуренция за кучу, создаются «арены» (см. следующую ссылку для справки http://www.bozemanpass.com/info/linux/malloc/Linux_Heap_Contention.html). Моя программа работает 24x7, и арены все еще иногда создаются через 2 недели. Я думаю, что в конечном итоге может быть столько же арен, сколько и потоков. ps(1) показывает тревожное потребление памяти, но я подозреваю, что на самом деле отображается только небольшая ее часть.

Каковы «накладные расходы» для пустой арены? (Насколько больше памяти используется на арену, чем если бы все выделение было ограничено традиционной кучей?)

Есть ли способ принудительно создать заранее n арен? Есть ли способ принудительно уничтожить пустые арены?


person rleir    schedule 31.01.2010    source источник
comment
Какую версию glibc и gcc вы используете?   -  person osgx    schedule 04.02.2010
comment
Ответ будет разным для разных версий glibc.   -  person osgx    schedule 04.02.2010
comment
вы используете ptmalloc? Какая версия gcc и glibc?   -  person osgx    schedule 07.02.2010
comment
Может быть до 65 тысяч арен. У потока нет отдельных арен, есть общий пул для всех потоков.   -  person osgx    schedule 07.02.2010
comment
Попробуйте: найти утечки памяти в программе; как можно больше повторно использовать потоки; используйте TCmalloc (из Google).   -  person osgx    schedule 07.02.2010
comment
@osgx спасибо за идеи. Я исправил утечки, прежде чем публиковать этот вопрос, и я знаю это, потому что традиционная куча не растет.   -  person rleir    schedule 13.02.2010


Ответы (5)


struct malloc_state (он же mstate, он же дескриптор арены) имеет размер

glibc-2.2 (256+18)*4 байта =~ 1 КБ для 32-битного режима и ~2 КБ для 64-битного режима. glibc-2.3 (256+256/32+11+NFASTBINS)*4 =~ 1,1–1,2 КБ для 32-разрядной версии и 2,4–2,5 КБ для 64-разрядной версии

См. файл glibc-x.x.x/malloc/malloc.c, структура malloc_state.

person osgx    schedule 04.02.2010
comment
Разве вам не нужно округлять его до следующего размера пейджингового блока MMU? Спасибо за ответ! - person rleir; 05.02.2010
comment
Это внутренний дескриптор арены. Каждый дескриптор арены помещается в сегмент mmap-ed. ограничение в 65k максимум mmaps жестко закодировано. Каждый mmap берет некоторые ресурсы из ядра ОС (VMA). - person osgx; 07.02.2010
comment
Все дескрипторы арены находятся в круговом списке, начинающемся с main_arena. Каждая новая арена помещается в начало области mmap со смещением sizeof(heap_info) = 4xsizeof(void*) = 16 или 32 байта. Куча (сегмент mmaped) выровнена и имеет размер от HEAP_MIN_SIZE до HEAP_MAX_SIZE. Он имеет родное выравнивание вызовов mmap (= page = 4k). Остальная часть кучи (после heap_info и mstate) используется для malloc_chunks (распределенные данные). - person osgx; 07.02.2010
comment
К сожалению, HEAP_MIN_SIZE = 32*1024 (32 КБ) HEAP_MAX_SIZE = 1024*1024 (1 МБ) - person osgx; 07.02.2010
comment
HEAP_MAX_SIZE = 1 МБ — это максимальный размер ARENA. Так что в большой программе будет МНОГО арен. - person osgx; 07.02.2010

Уничтожение арен... Пока не знаю, но есть такой текст (кратко - там написано НЕТ возможности уничтожения/урезания памяти ) из анализа http://www.citi.umich.edu/techreports/reports/citi-tr-00-5.pdf от 2000 г. (*немного устарел). Пожалуйста, назовите свою версию glibc.

Ptmalloc maintains a linked list of subheaps. To re-
duce lock contention, ptmalloc searchs for the first
unlocked subheap and grabs memory from it to fulfill
a malloc() request. If ptmalloc doesn’t find an
unlocked heap, it creates a new one. This is a simple
way to grow the number of subheaps as appropriate
without adding complicated schemes for hashing on
thread or processor ID, or maintaining workload sta-
tistics. However, there is no facility to shrink the sub-
heap list and nothing stops the heap list from growing
without bound. 
person osgx    schedule 06.02.2010
comment
Существует код для обрезки кучи (также известной как арена) (heap_trim). Но это работает только для полностью бесплатной арены. - person osgx; 07.02.2010
comment
Такой простой способ увеличения количества подкуч приведет к постоянному созданию арен (подкуч). Количество арен может расти и из-за фрагментации кучи. - person osgx; 17.02.2010

из malloc.c (glibc 2.3.5) строка 1546

/*
  -------------------- Internal data structures --------------------
   All internal state is held in an instance of malloc_state defined
   below. 
 ...
   Beware of lots of tricks that minimize the total bookkeeping space
   requirements. **The result is a little over 1K bytes** (for 4byte
   pointers and size_t.)
*/

Тот же результат, что и для 32-битного режима. Результат составляет чуть более 1 КБ.

person osgx    schedule 06.02.2010

Рассмотрите возможность использования TCmalloc из google-perftools. Он просто лучше подходит для поточных и долгоживущих приложений. И это очень БЫСТРО. Взгляните на http://goog-perftools.sourceforge.net/doc/tcmalloc.html, особенно для графики (чем выше, тем лучше). Tcmalloc вдвое лучше, чем ptmalloc.

person osgx    schedule 06.02.2010
comment
Спасибо за идею. Примечание: исходный вопрос не о скорости, мне не нужно, чтобы она была быстрее. - person rleir; 13.02.2010
comment
Преимуществом здесь является высокая скорость :) - person osgx; 15.02.2010

В нашем приложении основной стоимостью нескольких арен была «темная» память. Память, выделенная ОС, на которую у нас нет ссылок.

Образец, который вы можете видеть,

Thread X goes goes to alloc, hits a collision, creates a new arena.
Thread X makes some large allocations.
Thread X makes some small allocation(s).
Thread X stops allocating.

Освобождаются большие ассигнования. Но вся арена на высшей отметке последнего активного в данный момент распределения по-прежнему использует VMEM, и другие потоки не будут использовать эту арену, если они не столкнутся с конкуренцией на основной арене.

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

Наше (жадное до памяти) приложение может таким образом «тратить впустую» 10 процентов памяти, и в некоторых ситуациях это может сильно укусить.

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

person Peter    schedule 05.05.2011
comment
Спасибо за это. Я хотел бы выбрать этот ответ как «лучший», связанный с ответами osgx. - person rleir; 26.12.2011