Quasar 20 11 сентября, 2012 Опубликовано 11 сентября, 2012 · Жалоба Есть приложение, использующее pthread, по ходу выполнения приложения создаются новые потоки, выполнив свою работу они завершаются, делая просто return NULL. Я решил посмотреть, сколько памяти использует мое приложение cat /tmp/PID/status и чего-то не понял: Name: app State: S (sleeping) Tgid: 12718 Pid: 12718 PPid: 1 TracerPid: 0 Uid: 0 0 0 0 Gid: 0 0 0 0 FDSize: 32 Groups: VmPeak: 93568 kB VmSize: 93568 kB VmLck: 0 kB VmHWM: 1184 kB VmRSS: 1184 kB VmData: 90304 kB VmStk: 136 kB VmExe: 136 kB VmLib: 2796 kB VmPTE: 32 kB VmSwap: 0 kB Threads: 10 VmData с запуском нового потока только растет, и не уменьшается по его завершению, я так понимаю, что память выделенная под стек не освобождается. Это нормально или я неверно интерпретирую полученные данные? Плата вот эта. uname -a Linux buildroot 2.6.36-rc6 #732 Wed Jun 29 06:03:40 EDT 2011 armv5tejl GNU/Linux Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kurtis 0 11 сентября, 2012 Опубликовано 11 сентября, 2012 · Жалоба Если ничего не путаю, то смотреть нужно на RSS, это сколько реально памяти потребляет приложение. И еще использовать команду free, которая выводит обьем свободной памяти. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andron86 0 11 сентября, 2012 Опубликовано 11 сентября, 2012 · Жалоба Есть приложение, использующее pthread, по ходу выполнения приложения создаются новые потоки, выполнив свою работу они завершаются, делая просто return NULL. А завершаете их правильно? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Quasar 20 11 сентября, 2012 Опубликовано 11 сентября, 2012 · Жалоба А завершаете их правильно? Собственно так и завершаю: static void *rx_thread ( void *ptr ) { . . . return NULL; } Можно делать pthread_exit(), но я разницы не заметил. Да, я поглядел /proc/meminfo, свободная память вроде не уменьшается, то есть все таки нормально освобождается все, но мне не ясно, а что же это тогда за виртуальная память и почему она только растет? cat /proc/meminfo MemTotal: 60568 kB MemFree: 40236 kB Buffers: 16 kB Cached: 9920 kB SwapCached: 0 kB Active: 8132 kB Inactive: 2952 kB Active(anon): 1148 kB Inactive(anon): 12 kB Active(file): 6984 kB Inactive(file): 2940 kB Unevictable: 0 kB Mlocked: 0 kB SwapTotal: 0 kB SwapFree: 0 kB Dirty: 8 kB Writeback: 0 kB AnonPages: 1164 kB Mapped: 1816 kB Shmem: 12 kB Slab: 4640 kB SReclaimable: 2200 kB SUnreclaim: 2440 kB KernelStack: 400 kB PageTables: 280 kB NFS_Unstable: 0 kB Bounce: 0 kB WritebackTmp: 0 kB CommitLimit: 30284 kB Committed_AS: 184108 kB VmallocTotal: 956416 kB VmallocUsed: 266276 kB VmallocChunk: 686076 kB Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vshemm 0 11 сентября, 2012 Опубликовано 11 сентября, 2012 · Жалоба За потребление стека отвечает VmStk, за общее потребление физической памяти (приватный сет) - VmHWM и VmRSS, пик и текущее соответственно. VmData - это количество виртуальной памяти под данные. Растет обычно из-за хипа, его алгоритм так просто витруальную память не возвращает (из-за соображений производительности). По идее, если тест запустить надолго, рост должен остановиться на некотором значении. А для уменьшения VmData придется играть с низкоуровневыми функциями типа brk/sbrk, что является плохой идеей. Главное, чтобы VmHWM не рос неограниченно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kiathai 0 19 октября, 2012 Опубликовано 19 октября, 2012 · Жалоба А завершаете их правильно? При завершении потока, не освобождается память, выделенная под него (стек, описание потока и т.д.). Чтобы освободить эту память, требуется вызывать pthread_join() из какого-либо другого потока. Можно создавать потоки, которые будут удаляться автоматически. Для этого надо указывать атрибут PTHREAD_CREATE_DETACHED при создании потока. По умолчанию он не указан. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Andrew2000 0 22 октября, 2012 Опубликовано 22 октября, 2012 · Жалоба Можно делать pthread_exit(), но я разницы не заметил. если в потоке зарегистрировать: pthread_cleanup_push(thread_exit_func, (void*)&xxxx); .... pthread_cleanup_pop(1); функцию для "уборки мусора": void thread_exit_func (void * arg) { xxxx_type *xxxx = (thread_params *)arg; ..... } то завершать поток нужно именно по pthread_exit() - это гарантирует вызов "уборщика", а по return оно не вызывается Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alx2 0 23 октября, 2012 Опубликовано 23 октября, 2012 · Жалоба VmData с запуском нового потока только растет, и не уменьшается по его завершению, я так понимаю, что память выделенная под стек не освобождается. Это нормально или я неверно интерпретирую полученные данные? Посмотрите вывод команды pmap <PID> - там должно быть хорошо видно, что за блоки памяти выделяются процессом. Вы создаете detached threads или нет? Если нет, Вы в порождающем потоке выполняете pthread_join()? Если тоже нет, то ИМХО у Вас будет, как минимум, в памяти оставаться стек каждого отработавшего потока. Чтобы стек освобождался, Вы должны либо "открепить" созданный поток (выполнить pthread_detach(thr)), либо отслеживать его завершение в родительском потоке и выполнять pthread_join(). Как будет завершаться поток (через вызов pthread_exit() или через return NULL) значения не имеет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Quasar 20 7 ноября, 2012 Опубликовано 7 ноября, 2012 · Жалоба Посмотрите вывод команды pmap <PID> - там должно быть хорошо видно, что за блоки памяти выделяются процессом. Вы создаете detached threads или нет? Если нет, Вы в порождающем потоке выполняете pthread_join()? Если тоже нет, то ИМХО у Вас будет, как минимум, в памяти оставаться стек каждого отработавшего потока. Чтобы стек освобождался, Вы должны либо "открепить" созданный поток (выполнить pthread_detach(thr)), либо отслеживать его завершение в родительском потоке и выполнять pthread_join(). Как будет завершаться поток (через вызов pthread_exit() или через return NULL) значения не имеет. Я всегда жду удаления потоков pthread_join'ом. Вывод pmap не понял. В total он пишет, что использовано 270000 KByte, у меня всего 64МБайт, что это за пространство? pmap 1111 -x 1111: {no such process} /usr/bin/app -c /root/config.ini Address Kbytes PSS Dirty Swap Mode Mapping 00008000 92 80 0 0 r-xp /usr/bin/app 00027000 4 4 4 0 rwxp /usr/bin/app 00028000 132 52 52 0 rwxp [heap] 4000d000 4 4 4 0 rwxp [ anon ] 4000e000 28 12 0 0 r-xp /lib/librt-2.15.so 40015000 28 0 0 0 ---p /lib/librt-2.15.so 4001c000 4 4 4 0 r-xp /lib/librt-2.15.so 4001d000 4 4 4 0 rwxp /lib/librt-2.15.so 40025000 20 4 0 0 r-xp /usr/lib/libjson.so.0.0.1 4002a000 32 0 0 0 ---p /usr/lib/libjson.so.0.0.1 40032000 4 4 4 0 rwxp /usr/lib/libjson.so.0.0.1 40052000 4 4 4 0 rwxp [ anon ] 40059000 4 4 4 0 rwxp [ anon ] 40076000 128 17 0 0 r-xp /lib/libgcc_s.so.1 40096000 28 0 0 0 ---p /lib/libgcc_s.so.1 4009d000 4 4 4 0 rwxp /lib/libgcc_s.so.1 400a3000 24 24 0 0 r-xp /usr/lib/libao.so.4.0.0 400a9000 28 0 0 0 ---p /usr/lib/libao.so.4.0.0 400b0000 4 4 4 0 rwxp /usr/lib/libao.so.4.0.0 400b9000 4 4 4 0 rwxp [ anon ] 400cf000 16 2 0 0 r-xp /lib/libdl-2.15.so 400d3000 28 0 0 0 ---p /lib/libdl-2.15.so 400da000 4 4 4 0 r-xp /lib/libdl-2.15.so 400db000 4 4 4 0 rwxp /lib/libdl-2.15.so 400dd000 8 8 0 0 r-xp /usr/lib/ao/plugins-4/libpulse.so 400df000 28 0 0 0 ---p /usr/lib/ao/plugins-4/libpulse.so 400e6000 4 4 4 0 rwxp /usr/lib/ao/plugins-4/libpulse.so 400f6000 136 13 0 0 r-xp /lib/ld-2.15.so 40118000 4 4 4 0 rwxp [ anon ] 4011f000 4 4 4 0 r-xp /lib/ld-2.15.so 40120000 4 4 4 0 rwxp /lib/ld-2.15.so 40121000 8 8 0 0 r-xp /usr/lib/ao/plugins-4/liboss.so 40123000 32 0 0 0 ---p /usr/lib/ao/plugins-4/liboss.so 4012b000 4 4 4 0 rwxp /usr/lib/ao/plugins-4/liboss.so 4012c000 20 16 0 0 r-xp /usr/lib/ao/plugins-4/libalsa.so 40131000 28 0 0 0 ---p /usr/lib/ao/plugins-4/libalsa.so 40138000 4 4 4 0 rwxp /usr/lib/ao/plugins-4/libalsa.so 40146000 12 8 0 0 r-xp /usr/lib/libpulse-simple.so.0.0.3 40149000 28 0 0 0 ---p /usr/lib/libpulse-simple.so.0.0.3 40150000 4 4 4 0 rwxp /usr/lib/libpulse-simple.so.0.0.3 40182000 84 38 0 0 r-xp /lib/libpthread-2.15.so 40197000 28 0 0 0 ---p /lib/libpthread-2.15.so 4019e000 4 4 4 0 r-xp /lib/libpthread-2.15.so 4019f000 4 4 4 0 rwxp /lib/libpthread-2.15.so 401a0000 8 4 4 0 rwxp [ anon ] 401a2000 788 372 0 0 r-xp /usr/lib/libstdc++.so.6.0.16 40267000 28 0 0 0 ---p /usr/lib/libstdc++.so.6.0.16 4026e000 16 16 16 0 r-xp /usr/lib/libstdc++.so.6.0.16 40272000 8 8 8 0 rwxp /usr/lib/libstdc++.so.6.0.16 40274000 24 8 8 0 rwxp [ anon ] 4027a000 624 26 0 0 r-xp /lib/libm-2.15.so 40316000 32 0 0 0 ---p /lib/libm-2.15.so 4031e000 4 4 4 0 r-xp /lib/libm-2.15.so 4031f000 4 4 4 0 rwxp /lib/libm-2.15.so 40320000 1296 109 0 0 r-xp /lib/libc-2.15.so 40464000 28 0 0 0 ---p /lib/libc-2.15.so 4046b000 8 8 8 0 r-xp /lib/libc-2.15.so 4046d000 4 4 4 0 rwxp /lib/libc-2.15.so 4046e000 12 12 12 0 rwxp [ anon ] 40471000 4 0 0 0 ---p [ anon ] 40472000 8188 8 8 0 rwxp [ anon ] 40c71000 264 122 0 0 r-xp /usr/lib/libpulse.so.0.14.3 40cb3000 28 0 0 0 ---p /usr/lib/libpulse.so.0.14.3 40cba000 4 4 4 0 rwxp /usr/lib/libpulse.so.0.14.3 40cbb000 304 124 0 0 r-xp /usr/lib/pulseaudio/libpulsecommon-2.1.so 40d07000 28 0 0 0 ---p /usr/lib/pulseaudio/libpulsecommon-2.1.so 40d0e000 4 4 4 0 rwxp /usr/lib/pulseaudio/libpulsecommon-2.1.so 40d0f000 328 10 0 0 r-xp /usr/lib/libsndfile.so.1.0.25 40d61000 32 0 0 0 ---p /usr/lib/libsndfile.so.1.0.25 40d69000 8 8 8 0 rwxp /usr/lib/libsndfile.so.1.0.25 40d6b000 16 0 0 0 rwxp [ anon ] 40d6f000 712 136 0 0 r-xp /usr/lib/libasound.so.2.0.0 40e21000 32 0 0 0 ---p /usr/lib/libasound.so.2.0.0 40e29000 16 16 16 0 rwxp /usr/lib/libasound.so.2.0.0 40e2d000 4 0 0 0 ---p [ anon ] 40e2e000 8188 8 8 0 rwxp [ anon ] 4164e000 4 0 0 0 ---p [ anon ] 4164f000 8188 8 8 0 rwxp [ anon ] 41e4e000 4 0 0 0 ---p [ anon ] 41e4f000 8188 8 8 0 rwxp [ anon ] 426d3000 4 0 0 0 ---p [ anon ] 426d4000 8188 8 8 0 rwxp [ anon ] 42ed3000 4 0 0 0 ---p [ anon ] 42ed4000 8188 8 8 0 rwxp [ anon ] 4376a000 4 0 0 0 ---p [ anon ] 4376b000 8188 8 8 0 rwxp [ anon ] 43f6a000 4 0 0 0 ---p [ anon ] 43f6b000 8188 8 8 0 rwxp [ anon ] 44812000 4 0 0 0 ---p [ anon ] 44813000 8188 8 8 0 rwxp [ anon ] 45012000 4 0 0 0 ---p [ anon ] 45013000 8188 12 12 0 rwxp [ anon ] 45902000 4 0 0 0 ---p [ anon ] 45903000 8188 8 8 0 rwxp [ anon ] 46200000 132 40 40 0 rwxp [ anon ] 46221000 892 0 0 0 ---p [ anon ] 46300000 132 40 40 0 rwxp [ anon ] 46321000 892 0 0 0 ---p [ anon ] 46400000 4 0 0 0 ---p [ anon ] 46401000 8188 20 20 0 rwxp [ anon ] 46c17000 4 0 0 0 ---p [ anon ] 46c18000 8188 8 8 0 rwxp [ anon ] 47417000 4 0 0 0 ---p [ anon ] 47418000 8188 8 8 0 rwxp [ anon ] 47c17000 4 0 0 0 ---p [ anon ] 47c18000 8188 20 20 0 rwxp [ anon ] 48417000 4 0 0 0 ---p [ anon ] 48418000 8188 8 8 0 rwxp [ anon ] 48c17000 4 0 0 0 ---p [ anon ] 48c18000 8188 20 20 0 rwxp [ anon ] 49417000 4 0 0 0 ---p [ anon ] 49418000 8188 8 8 0 rwxp [ anon ] 49c17000 4 0 0 0 ---p [ anon ] 49c18000 8188 20 20 0 rwxp [ anon ] 4a417000 4 0 0 0 ---p [ anon ] 4a418000 8188 8 8 0 rwxp [ anon ] 4ac17000 4 0 0 0 ---p [ anon ] 4ac18000 8188 20 20 0 rwxp [ anon ] 4b418000 4 0 0 0 ---p [ anon ] 4b419000 8188 20 20 0 rwxp [ anon ] 4bc18000 4 0 0 0 ---p [ anon ] 4bc19000 8188 8 8 0 rwxp [ anon ] 4c418000 4 0 0 0 ---p [ anon ] 4c419000 8188 8 8 0 rwxp [ anon ] 4cc18000 4 0 0 0 ---p [ anon ] 4cc19000 8188 20 20 0 rwxp [ anon ] 4d418000 4 0 0 0 ---p [ anon ] 4d419000 8188 8 8 0 rwxp [ anon ] 4dc18000 4 0 0 0 ---p [ anon ] 4dc19000 8188 20 20 0 rwxp [ anon ] 4e418000 4 0 0 0 ---p [ anon ] 4e419000 8188 8 8 0 rwxp [ anon ] 4ec18000 4 0 0 0 ---p [ anon ] 4ec19000 8188 20 20 0 rwxp [ anon ] 4f418000 4 0 0 0 ---p [ anon ] 4f419000 8188 8 8 0 rwxp [ anon ] 4fc18000 4 0 0 0 ---p [ anon ] 4fc19000 8188 12 12 0 rwxp [ anon ] 50480000 4 0 0 0 ---p [ anon ] 50481000 8188 20 20 0 rwxp [ anon ] bef06000 132 8 8 0 rw-p [stack] -------- ------ ------ ------ ------ total 270064 1837 708 0 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alx2 0 9 ноября, 2012 Опубликовано 9 ноября, 2012 (изменено) · Жалоба Я всегда жду удаления потоков pthread_join'ом. Вывод pmap не понял. Вот такие группы блоков памяти 4f418000 4 0 0 0 ---p [ anon ] 4f419000 8188 8 8 0 rwxp [ anon ] есть ни что иное как стек потока. pthread выделяет стек двумя кусочками: 4k и все остальное. Я насчитал у Вас 32 дочерних потока со стеками по 8 мегабайт у каждого. Это действительно так? Если родительский поток вызывает pthread_join, то после завершения дочернего потока выделенная под стек память должна была освободиться. В total он пишет, что использовано 270000 KByte, у меня всего 64МБайт, что это за пространство? Есть такое понятие как виртуальная память. Что это такое, можно почитать хотя бы тут: http://ru.wikipedia.org/wiki/Виртуальная_память В linux пользовательские процессы работают с виртуальной памятью, а 64 Мбайта, о которых Вы пишете - это реальная физическая память. Виртуальной памяти у процесса может быть сколько угодно. Пока процесс к ней не обращается, она существует только в виде записи в таблицах. Еще обратите внимание на поле Dirty. Если я правильно понимаю, оно показывает объем памяти, реально использованный процессом в данном блоке. Например, в процитированном мной фрагменте видно, что поток использовал 8 кбайт из 8 Мбайт, выделенных ему для стека. Изменено 9 ноября, 2012 пользователем alx2 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alx2 0 9 ноября, 2012 Опубликовано 9 ноября, 2012 (изменено) · Жалоба Если родительский поток вызывает pthread_join, то после завершения дочернего потока выделенная под стек память должна была освободиться. Небольшое уточнение. Сейчас я провел небольшой эксперимент. В моей реализации libpthread pthread_join() освобождает все стеки кроме пяти последних. Если затем создать 5 новых потоков, они повторно заюзают те блоки, которые остались после завершения предыдущих. Вот тестовая программка, с которой можно все это увидеть: #include <stdio.h> #include <unistd.h> #include <pthread.h> void *child(void *context) { sleep(5); return NULL; } int main() { // Создаем 30 потоков pthread_t thr[30]; for(int i = 0; i < 30; i++) pthread_create(&thr[i], NULL, child, NULL); printf("threads created\n"); // Ждем завершения всех потоков for(int i = 0; i < 30; i++) pthread_join(thr[i], NULL); printf("threads ended\n"); sleep(5); return 0; } Сравните карту памяти сразу после запуска и после завершения дочерних потоков. Попробуйте убрать pthread_join() и Вы увидите, что после завершения всех потоков вся их память остается занятой. Изменено 9 ноября, 2012 пользователем alx2 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Quasar 20 26 ноября, 2012 Опубликовано 26 ноября, 2012 · Жалоба Я насчитал у Вас 32 дочерних потока со стеками по 8 мегабайт у каждого. Это действительно так? Да, эти потоки реально существуют. По поводу реальной и виртуальной памяти, я в общем в курсе. Я поднял этот вопрос с целью понять, не течет ли у меня память. И из обсуждения не совсем понял, как понять точно, что память течет. То есть, запустить приложения на длительный срок, просмотреть, сколько было выделено, сколько освобождено. С учетом того, что приложение не должно разрастаться по потреблению памяти со временем. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrewlekar 0 27 ноября, 2012 Опубликовано 27 ноября, 2012 · Жалоба Такие утечки памяти хорошо ловятся valgrind'ом. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться