LINUX.ORG.RU

Разбухание памяти в программах на C/C++ в Linux


0

0

Я на днях прочитал, что реализация функций malloc и free в glibc не выполняет никакой работы по сокращению объёма используемой памяти, не считая системного вызова brk() или как там его, в результате чего получается фрагментация используемой программой оперативной памяти.

Интересно стало, как с этим можно бороться и как вообще люди борются?

Кстати, прошёл слушок, что возможно заюзать реализацию malloc из openbsd, неужели правда?

P.S. Вопрос навеян тенденцией всё большего и большего пожирания памяти линуксовыми програмами, например, firefox, потребление памяти которым просто легендой стало.

★★

Ответ на: комментарий от anonymous

>A browser.*.cache.enable ставил в false ?

Нет пока, посмотрю.

>Программку можно такую:

Ага, спасибо, я похожий тестик под линукс использовал, но твой будет удобнее.

>Т.к. free() делаем не с конца и SIZE=1024 < MMAP_THRESHOLD, то под linux она не отдает память до освобождения n-го блока.

Ещё надо попробовать SIZE совсем маленьким сделать...

>mr, спасибо, порадовал. Возможно openbsd-шный malloc можно собрать под linux.

Да, это наиболее интересный вопрос. При попытке "в лоб" (gcc -shared -fpic obsd-malloc.c -o malloc.so) не получилось.

>Имхо, надо эти опыты кратко изложить в отдельной теме, т.к. эта уже уплыла вниз. Возьмешся? :) Мужыки-та не знають!

Надо всё тщательно проверить!

P.S. Перезагружаюсь в openbsd :-)

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

Вопрос в том не использует ли оно какие-то специфические возможности openbsd ядра.

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

Надо смотреть, как там вызывается mmap/munmap.

Специфич. возможности ядра, имхол, только в кол-ве вызовов mmap в единицу времени?

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

Протестировал я, возможно, новости не самые оптимистичные.

Если тестировать твоей программой, то всё хорошо отдаётся, при каждом нажатии 1 мегабайт, типа:
$ ps -o command,vsz,rss|grep a.out
./a.out 264912 266108
$ ps -o command,vsz,rss|grep a.out
./a.out 263948 265152
Как и ожидалось...

А вот если освобождать память через один:
sleep(10);
printf("freeing...\n");
for (n=0; n < N-1; n+=2) {
free(p[n]);
}
то нифига не отдаётся :(Но если же при этом SIZE увеличить до 4096, то
после free память уменьшается в 2 раза, как и ожидалось.
Ещё опыт: делаем SIZE равным 2048 (при N==1024*32) и имеем использование памяти 64M, и ничего не отдаётся.
Делаем SIZE равным 2049 и имеем использование памяти 128M, которое после free уменьшается и становится равным 64M.

Итак, похоже дело обстоит так. OpenBSD размещает переменные в областях пропорциональных 4096 байт.
Причём если новая переменная не укладывается в "старую" область, то для неё создаётся новая область.
Что и должно быть (ведь эти области создаются mmap).
Область отдаётся системе тогда и только тогда, когда она полностью освободилась.

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

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

Похоже на правду.

Интересно еще посмотреть на вывод malloc_stats() в отладочной сборке mozilla под OpenBSD (./configure --enable-trace-malloc --enable-debug)

OpenBSD поставить не могу, т.к. некуда.

Пост в bugzilla.mozilla.org можно написать так [sorry for my terrible english]:

1. Blah-blah-blah about mozilla's & Co. VM consumption on GNU/Linux.

Mozilla (seamonkey, firefox) compiled with --enable-trace-malloc demonstrates the following pattern of the dynamic memory usage during a session, disk and memory caches being disabled:

1. < malloc_stats() output upon a clean start with about:blank >

2. < malloc_stats() output upon opening multiple tabs >

3 < malloc_stats() output upon closing all the tabs and returning to about:blank >

Obviously, such a tendency represents a great zhopa as the VM assigned to the mozilla-bin process monotonically increases on average in course of session. Such a behaviour inevitably results in an inacceptable slowing down of the system, bla-blah-blah.

Nevertheless, mozilla compiled with an alternative openbsd-like memory allocator (blah-blah-blah) shows more reasonable VM size dynamics:

< Here the same 1,2,3 items follow >

Ну или на крайний случай:

Nevertheless, mozilla running on top of OpenBSD 3.8 shows more reasonable VM footprint:

< items no. 1,2,3 >

Should this kind of *alloc/free realization be cheked into mozilla CVS ?

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

>Другое дело, что проблемму это решает лишь частично.

А вообще для firefox не так, если там нет утечек памяти или вообще переменных, которые должны оставаться после закрытия табов/страниц, то проблему этот аллокатор должен решить полностью.

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

Ну ты меня нарузил :) Итак полночи openbsd устанавливал :)

А вдруг геморройно будет на openbsd перекомпилировать firefox? Да и долго это...

Вот если бы удалось скомпилиовать openbsd'шный malloc на линуксе сразу в .so, то не пришлось бы вообще эту мозиллу перекомпилировать (LD_PRELOAD и всё).

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

А собрать firefox с --enable-trace-malloc firefox можешь под OpenBSD?

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

> Вот если бы удалось скомпилиовать openbsd'шный malloc на линуксе сразу в .so

Опередил :) Дык посмотри, как в openbsd вызывается mmap() и как сделаны блокировки для threads, там кода немного.

Извини, сейчас не могу на это долго смотреть, на работе.

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

не случайно. В bugzilla мои посты были.

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

Действительно, чего-то с тредами. Подсунул нужные *.h файлы, скомпилировалось, при попытке запустить любую програму говорит "symbol lookup error: ./malloc.so: undefined symbol: __isthreaded". Да, малой кровью тут не получится, надо разбираться...

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

Осталась сущая безделица: ко всем таким undefined в линуксе переменным/функциям найти их линуксовый эквивалент.

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

firefox сможешь под openbsd собрать с trace-malloc (см. выше)?

Как минимум, надо запостить в bugzilla сравнение потребления VM под linux и openbsd.

Предлагаю сделать новую тему в Talks, пусть народ с аналогичной проблемой отметится в bugzilla.

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

>firefox сможешь под openbsd собрать с trace-malloc (см. выше)?

А trace-malloc это что значит? Он будет вывод malloc_stats куда-то печатать (и куда?) ?

>Как минимум, надо запостить в bugzilla сравнение потребления VM под linux и openbsd.

Я сомневаюсь что это поможет -- никто из разработчиков firefox может и не захотеть портировать аллокатор на линукс.

>Предлагаю сделать новую тему в Talks, пусть народ с аналогичной проблемой отметится в bugzilla.

Ну сделай, в чём вопрос.

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

> А trace-malloc это что значит? Он будет вывод malloc_stats куда-то печатать (и куда?) ?

stderr | stdout

> никто из разработчиков firefox может и не захотеть портировать аллокатор на линукс.

hoard и dlmalloc они в разное время совали в cvs.

>Ну сделай, в чём вопрос.

У меня нет OpenBSD, так что тебе желательно в ту тему написать про свои опыты. :)

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

>stderr | stdout

Понятно.

>hoard и dlmalloc они в разное время совали в cvs.

Так ведь это ж уже было готово для линукса--а тут портировать надо.

>У меня нет OpenBSD, так что тебе желательно в ту тему написать про свои опыты. :)

Я не понял, ты в теме хочешь предложить, чтобы проголосовали за баг или чтобы я написал про эти опыты с openbsd?

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

> ты в теме хочешь предложить, чтобы проголосовали за баг или чтобы я написал про эти опыты с openbsd?

погоди, сейчас напишу сообщение туда.

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

Мысли вслух: чегой-то тема в Talks не поимела конструктивного продолжения.

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

А вот и не ура. В этом тоже выдаёт ту же ошибку:

misc/prnetdb.c:1192: error: conflicting types for `getprotobyname_r'

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

Делаю ./configure --enable-trace-malloc --enable-application=browser, затем запускаю gmake, вскоре вываливается с этой ошибкой. В гугле ответа не нашёл, мало что там есть по поводу "conflicting types for `getprotobyname_r'".

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

Этот?
$ cat ~/.mozconfig
# sh
# Build configuration script
#
# See http://www.mozilla.org/build/unix.html for build instructions.
#

# Options for client.mk.
mk_add_options MOZ_CO_PROJECT=browser
mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj-@CONFIG_GUESS@

# Options for 'configure' (same as command-line options).
ac_add_options --enable-application=browser
ac_add_options --enable-trace-malloc

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

Для firefox надо так:

export MOZ_PHOENIX=1 mk_add_options MOZ_PHOENIX=1

# Options for client.mk. mk_add_options MOZ_CO_PROJECT=browser mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj-@CONFIG_GUESS@

# Options for 'configure' (same as command-line options).

ac_add_options --prefix=/path/to/installation

ac_add_options --enable-application=browser

ac_add_option --enable-trace-malloc ac_add_option --enable-debug

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

mr, в openbsd firefox собирается через порт:
http://www.openbsd.org/cgi-bin/cvsweb/ports/www/mozilla-firefox/

Makefile cодержит инструкции по сборке порта.

чтобы установить порты, необходимо взять ports.tar.gz от установленной
версии openbsd и распаковать в /usr:

  # cd /usr && tar xzf ~/ports.tar.gz

чтобы обновить порты до -stable:

  # cd /usr/ports
  # cvs -z3 -fqd anoncvs@anoncvs.ca.openbsd.org:/cvs up -PAdrOPENBSD_3_8 .

порт устанавливается так:

  # cd /usr/ports/www/mozilla-firefox
  # make install clean CLEANDEPENDS=Yes

можно собрать только пакадж например:

  # make package

в общем -- man ports, man bsd.port.mk

чтобы добавить опции сборки, необходимо отредактировать строку
с CONFIGURE_FLAGS.

cu.

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

это другой анонимус, лучше его слушай про сборку :)

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

Из портов собирай, выше правильно говорят. Ты BSD что ли никогда не видел?

В OpenBSD патчей на этот distfile накладывается несколько десятков.

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

Убедись сначала, что умолчальная сборка из ports работает. Потом можно экспериментировать с --enable-debug --enable-trace-malloc

-- тот анонимус

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

Понятно. Да, с BSD столкнулся в первый раз.

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

yep.

положи firefox-....tar.gz, который ты скачал с chg.ru в
/usr/ports/distfiles, а то он перекачивать будет.

и посмотри с каким gtk собирается. (там с 2.x кажись)

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

> что, прийдётся всё снова перекомпилировать ??

лучше перекомпилировать во избежание.

То есть сначала make distclean && ./configure && make

как в openbsd это делается, уточни.

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

Сделал так, а он (make package) говорит, что checksum не сходится :( Прийдётся перекачивать.

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