LINUX.ORG.RU

фрагментация памяти


0

3

Вопрос таков: есть программа которая работает 24/7 и интенсивно работает с памятью, выделение идет от 10 до 4000 байт. Через неделю работы программа отжирает 200-300Кб памяти и не возвращает ее системе.
Гугл выдал рекомендации писать собственный аллокатор памяти, но как то делать это не хочется.
Есть ли либы, типа бздовой которая к фоксу прикручивалась, для борьбы с фрагментацией памяти?

>Через неделю работы программа отжирает 200-300Кб памяти

Если речь идет о PC и «Кб» — не опечатка, то сие есть некритично.

>Гугл выдал рекомендации писать собственный аллокатор памяти

Можно оптимизировать работу с памятью в самом приложении: выделять временные объекты на стеке с помощью alloca (не всегда возможно) или создавать для них пул, использовать интрузивные контейнеры (sys/queue.h, , объединять блоки памяти:

struct string_pair {
  const char *first, *second;
};

struct string_pair *make_string_pair(const *s1, const *s2)
{
  int l1 = strlen(s1) + 1, l2 = strlen(s2) + 1;
  struct string_pair *pair = malloc(sizeof(*pair) + l1 + l2);
  pair->first = (const char*)memcpy((char*)pair + sizeof(*pair), s1, l1);
  pair->second = (const char*)memcpy((char*)pair + sizeof(*pair) + l1, s2, l2);
  return pair;
}

Хоть все это и звучит весьма длинно, но это гораздо проще, чем написать аллокатор, который «сделает зашибись».

linuxfan ()

возьми нормальный язык с GC(tracing GC! не reference counting)

Love5an ()

1. А 200-300 Кб - это критично? В смысле сколько всего ОЗУ присутсвует? 2. Рост идёт дальше или так и останавливается на 200-300 Кб?

nanoo_linux ()

1) я бы прогнал прогу под валгриндом, чтобы удостовериться, что память не течет

2) 300кб - это очень мало, как тут уже написали

3) если работа с памятью интенсивная, то можно поиграться с tcmalloc от того же гугла

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

>можно поиграться с tcmalloc

tcmalloc написан для того, чтобы эффективно работать в многопоточной среде. Для борьбы с фрагментацией он не подходит.

linuxfan ()

Придётся не просто писать свой аллокатор, а существенно переделывать способ работы с объектами, считай ~переписывание приложения. Либы не помогут.

mashina ★★★★★ ()

Какой tmalloc, нахер?

Garbage Collection надо использовать, идиоты.
Везде. Кроме, может быть, модулей разных тухлых ОС, в которых GC нет.
Сейчас даже на кофеварку можно вполне упихнуть рантайм языка с нормальным GC.

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

>Garbage Collection надо использовать, идиоты.

gc как раз для идиотов. Медленных неповоротливых идиотов. Таких как жабка и CL.

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

Читай до просветления:
ftp://ftp.cs.utexas.edu/pub/garbage/bigsurv.ps

GC сейчас не пользуются в трех случаях - в программировании ведер(1), потому что поддерживают инфраструктуру для идиотов, пишущих прикладное ПО на языках без GC(2), и в программировании микроконтроллеров и вообще, встраиваемых, систем(3); в последнем случае - либо по причине отсутствия динамической памяти вообще, либо от незнания того факта, что ручное управление памятью и, тем более, подсчет ссылок, несет большие накладные расходы, чем хороший отслеживающий GC.

Love5an ()
Ответ на: комментарий от trashymichael

>>может ты ее просто не освобождаешь?

если free не освобождает после calloc и malloc, то да, я ее не особождаю

ZaeLam3l ()
Ответ на: комментарий от nanoo_linux

>>1. А 200-300 Кб - это критично? В смысле сколько всего ОЗУ присутсвует? 2. Рост идёт дальше или так и останавливается на 200-300 Кб?

ОЗУ 2 гига, максимальный рост был ~700Кб, софтина в процессе допиливания и долго ей поработать не удается

ZaeLam3l ()
Ответ на: комментарий от Love5an

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

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

Ну и об остальном бреде:

в программировании ведер(1), потому что поддерживают инфраструктуру для идиотов, пишущих прикладное ПО на языках без GC

Потому что GC вносит недетерминированные задержки, с другой стороны, запрет на его вызов в критических фрагментах ядра может привести к падению от нехватки памяти.

в программировании микроконтроллеров и вообще, встраиваемых, систем(3)

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

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

> Накладные расходы на GC (особенно в случае больших объемов данных)

огромны.


Пруфлинк будет?

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

>Пруфлинк будет?

По идее, пруфлик должен располагаться в голове между правым и левым ушами и называться мозг. Если воспользоваться этим пруфлинком по назначению, можно прийти к понимаю того, что сборщику мусора необходима некая дополнительная информация (если хочешь, список объектов), которая, в принципе, эквивалентна заголовкам блоков памяти в куче. Дальше хуже: ему нужна информация о ссылках на каждый объект, а это либо дополнительные структуры в памяти, являющиеся по сути «навороченными указателями», либо просмотр памяти приложения в поисках ссылок на объекты в куче (как boehm-gc делает).

Но если у тебя проблемы с доступом к /dev/brain, то вот в разжеванном виде: http://en.wikipedia.org/wiki/Garbage_collection_%28computer_science%29#Disadv...

Особенно веселит:

Memory may leak despite the presence of a garbage collector, if references to unused objects are not themselves manually disposed of.

Если переверсти это на понятный круглоскобочным язык: надо ручками избавляться от ссылок на объекты. Также это можно делать автоматически при покидании лексической области видимости указателя (ой, у скобочных она же еще динамической бывает!), но вроде бы это уже где-то есть. Постой! Это же уже есть в C++! В C++ память _уже_ не течет при условии, что руки растут из правильного места.

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

> если переверсти это на понятный круглоскобочным язык:

Что ёрничаешь, опять с «гуманитарной помощью» проблемы? Отключи у себя эту функцию на время, попробуй подумать тем самым мозгом.

В C++ память _уже_ не течет при условии, что руки растут из

правильного места



У меня в C++ память никогда не текла. Но дело ведь в другом, не в утечках. Вообще, какие есть причины для того, что бы ручное управление памятью было более эффективным, чем автоматическое? С одной стороны, при ручном управлении никакой дополнительной информации хранить не нужно, это плюс. С другой стороны, при этом может использоваться фактически только универсальный, а значит, не самый эффективный метод её перераспределения. Основная проблема в долгом выделении памяти стандартным механизмом. Это минус. Понимаешь, что когда процессом выделения и освобождения управляет программа, а не человек, то это может быть более эффективным? Что будет более выгодно зависит от задачи и от доступной реализации GC. Когда-то GC были медленными. Но над ними работали, писали дисертации и т.п. Уже сейчас вопрос о том, какой вариант управления памятью является более выгодным является неоднозначным. А в обозримом будущем GC скорей всего уверенно выйдет в лидеры.

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

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

ОЗУ 2 гига, максимальный рост был ~700Кб, софтина в процессе допиливания и долго ей поработать не удается

Чего-то мне подсказывает, что там где-то мемори лик. валгридом проверь.

nanoo_linux ()
Ответ на: комментарий от archimag

>С одной стороны, при ручном управлении никакой дополнительной информации хранить не нужно, это плюс.

Нет, это на самом деле фигня. Главный плюс при ручном управлении: мы можем использовать память эффективно. К примеру, оставлять в памяти только долгоживущие объекты, а в промежуточных вычислениях использовать пулы. Устраняет проблему фрагментации на 99.99%. А еще можно вручную же объединять блоки памяти, о чем я уже писал. Вариантов массы, к несчастью все они задействуют мозг, а с этим, судя по всему, у населения планеты какие-то трудности.

Основная проблема в долгом выделении памяти стандартным механизмом.

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

А в обозримом будущем GC скорей всего уверенно выйдет в лидеры.

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

Раз уж на то пошло, разработки начались относительно недавно, потому что до недавнего времени железо физически не могло не тормозить при работе gc. За последнюю пятилетку железки фантастически прибавили в производительности, быдлокодеры оживились, но, увы, железочки уперлись в потолок по частоте и дальше могут наращивать только ядра. А gc в многопоточной среде — это...

Если /dev/brain не замерз от более чем прохладной зимы, ты сам поймешь, почему gc сосет в многопоточной среде.

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

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

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

Ты отказываешься думать и игнорируешь факты. Но мне, вообщем-то, всё равно. Прогресс двигают не такие как ты. К счастью.

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

>Ты отказываешься думать и игнорируешь факты. Факты

  • жаба тормозит и потребляет много памяти.
  • sbcl потребляет много памяти
  • вызов gc занимает время. Суммарно это может быть меньше, чем время, потраченное на вызовы malloc/free, но это занимает фриз всего приложения на заметный человеческому восприятию интервал
  • писать приложения с подсчетом ссылок на C++ легко, приятно и память не течет

Я перечислил факты, которые ты упорно игнорируешь. Перечисли факты, которые игнорирую я.

linuxfan ()
Ответ на: комментарий от mashina

> Придётся не просто писать свой аллокатор, а существенно переделывать способ работы с объектами, считай ~переписывание приложения. Либы не помогут.

Не обязательно. Можно попробовать libumem.

mukoh ()

>> Неужели, в Mozilla не смогли найти таких гениальных программистов, как ты и linuxfan, у которых нихуя никогда память не течет в C++?

Или firefox - не сложная программа?

т.к. ноги у него растут от нетскейпа, думаю код там в некоторой степени ужасен.

и я не уверен, что он именно течет:

- я на своей машине не вижу заметного увеличения занятой памяти даже если ФФ запущен 2-3 дня.

- возможно дело в этой самой фрагментации.

И я вовсе не гениальный, но пока еще в состоянии написать программу на сях которая не течет. Это не так уж и сложно.

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

> думаю код там в некоторой степени ужасен.

Говорят, что «ужасен» по отношению к оригинальному коду нетскейпа слишкмо мягкое выражение ;)

archimag ★★★ ()

free не возвращает память систе, если ты об этом. Программа может только расти. man sbrk. Ну и valgrind для дебага утечек если они есть.

PS я надеюсь ты не о том что память системе не отдаётся после умирания процесса.

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

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

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

> ссылку не читал

Ъ?

просто знаю что большинство реализаций malloc не шринкают сегмент данных.

Ну а так да - с помощью sbrk границу сегмента данных можно двигать в любую сторону, но вот если начать пользоваться malloc/free - то уже фиг..

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

Ъ?

Да нет, просто я читал линуховый man по brk, не думаю что что-то новое узнаю из твоего мана. Или узнаю?

Я пробовал использовать sbrk(запоминать brk, делать malloc(), free() и возвращать brk в старое значение), программа навернулась :(. Думаю во всём был виновать libc. Дело, правда, было во фре(если не ошибаюсь).

true_admin ★★★★★ ()

slab allocator поможет тебе

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

dimon555 ★★★★★ ()

У моего коллеги когда-то был аналогичный баг.
Сейчас вытащил из репозитория версию, которая так себя вела — не репродьюсится. По словам того чувака, который его фиксил — проблема была в glibc-шном аллокаторе, который допускал значительную фрагментацию и тупо не по-долгу возвращал страницы системе. Пофиксилось созданием своего аллокатора для временных объектов, по образу и подобию кернельного слаб-аллокатора.

Remington ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.