URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 9281
[ Назад ]

Исходное сообщение
"Размер процесса. Используемая память. Потоки."

Отправлено Fx , 14-Ноя-11 05:48 
Здравствуйте,

Есть демон на си++ с потоками. По моим подсчетам, должен занимать в памяти ~10 мегабайт, а он по данным из top жирнеет до 300M.

все объекты из памяти, сериализуются на диск и там уже реально отражают картину, и занимают 16 мегабайт суммарно. почему при перезапуске, при считывании этих объектов с диска, программа сново жирнеет до 160М примерно?

Думаю, может это потоки, каждый дублирует общую память? Т.е. сколько всего памяти нужно умножается на количество потоков? (хотя тоже не похоже, потоков при старте всего 6) На что смотреть? Как искать причину?

Спасибо

пс. да, и раз уже о потоках написал, то не понимаю почему gdb показывает что потоков 7, а не 6... 4 + 1 + поток прородитель main = 6.... откуда 7мой?


Содержание

Сообщения в этом обсуждении
"Размер процесса. Используемая память. Потоки."
Отправлено ACCA , 14-Ноя-11 07:12 
> Здравствуйте,
> Есть демон на си++ с потоками. По моим подсчетам, должен занимать в
> памяти ~10 мегабайт, а он по данным из top жирнеет до
> 300M.

libс, stdc++, да мало ли голодных детей с ложками? И потом, ты какую память считаешь?


"Размер процесса. Используемая память. Потоки."
Отправлено Fx , 14-Ноя-11 12:27 
>> Здравствуйте,
>> Есть демон на си++ с потоками. По моим подсчетам, должен занимать в
>> памяти ~10 мегабайт, а он по данным из top жирнеет до
>> 300M.
> libс, stdc++, да мало ли голодных детей с ложками? И потом, ты
> какую память считаешь?

метафора хороша, понравилось.
по теме - память из "top" колонка RES / SIZE, по сути не важно какая - все равно много. например: 179М - в опреативке, 262М фактически. и это только после запуска.

вчера лег отдыхать, после того как написал. и мысль как раз о std::map не давала покоя. самые многочисленные объекты хранятся в map<int,Object*>, где int - уникальный ключ. возможно эти map выжирает очень много памяти. сейчас буду проверять через свойство capaticy() вроде или дебагером, который ниже Вова посоветовал.

map - этот прийдется заменять на hash_map какой-нибудь видимо? искал раньше, видел hash_map от гугл неплохой по описанию, но пока не изучал. решил, что для прототипа и std::map подходит. да и с int ключем вроде он достаточно быстрый должен быть.

оптимизировать потребление std::map памятим возможно?

спасибо


"Размер процесса. Используемая память. Потоки."
Отправлено Вова , 14-Ноя-11 09:40 
Каждый поток резервирует место под свой стек, по умолчанию это 8 мб, поэтому даже два потока съедят 16 метров, что больше ожидаемых вами 10ти.  Далее, память (куча) общая у всех потоков, поэтому никакие объекты c++ не дублируются по количеству потоков. Ошибки работы с памятью отлично отслеживаются валгриндом, практически все - кроме блоков, потраченных под вышеупомянутые стеки, для их деаллокации необходимо обязательно использовать либо pthread_join() либо pthread_detach().

"Размер процесса. Используемая память. Потоки."
Отправлено Fx , 14-Ноя-11 12:40 
> Каждый поток резервирует место под свой стек, по умолчанию это 8 мб,
> поэтому даже два потока съедят 16 метров, что больше ожидаемых вами
> 10ти.  Далее, память (куча) общая у всех потоков, поэтому никакие
> объекты c++ не дублируются по количеству потоков. Ошибки работы с памятью
> отлично отслеживаются валгриндом, практически все - кроме блоков, потраченных под вышеупомянутые
> стеки, для их деаллокации необходимо обязательно использовать либо pthread_join() либо
> pthread_detach().

спасибо за наводку на дебагер, сейчас почитаю и попробую разобраться в нем. выше описал дополнительные моменты, скорей всего проблема в std::map<int,Object*> (около 60000) объектов на один map

также использую std::map<std::string, Object*> но количество объектов не так многочисленно (сейчас 2, будет до 100) на данный момент можно принебречь.

по поводу умолчания на поток по 8 мб, если ли мозможнось выделять меньше памяти и оправдано ли это?

пс. 10M - это сумма по объектам, после сериализации на диск. в памяти они должны занимать еще меньше, т.к. на диске строки используются, а в памяти - указатели.


"Размер процесса. Используемая память. Потоки."
Отправлено Fx , 14-Ноя-11 16:17 
валгринд еще не поставил (старя весия фрибсд у меня) качаю новый дистрибутив.

std::map - отпадают, убрал самые крупные для теста - использование памяти заметно не упало,
а вот когда убираю объекты, хранящиеся в этих map, то сразу прихожу к 18M на процесс.

sifeof (объект) = 92 байт (без учета в нем пар map<int,int> - обычно количество 1-2 пары, т.е. в памяти пусть 110 байт будет даже.
на диске после сериализации в среднем 78 байт на объект.

70000 объектов = около 7 мегабайт.
7 * 4 = 28 мегабайт на эти объекты.
но почему приложение жирнеет при них на более чем 100 мегабайт ( 120-230 мб)...



"Размер процесса. Используемая память. Потоки."
Отправлено Fx , 14-Ноя-11 21:48 
методом научного тыка нашел:
проблема в мутексах. один инициализированый мутекс занимает на вскидку около 600 байт(read/write мутекс) и 200 байт если перейти на обычные мутексы. что дальше делать не знаю и почему так. это очень много.

"Размер процесса. Используемая память. Потоки."
Отправлено Вова , 15-Ноя-11 14:17 
> методом научного тыка нашел:
> проблема в мутексах. один инициализированый мутекс занимает на вскидку около 600 байт(read/write
> мутекс) и 200 байт если перейти на обычные мутексы. что дальше
> делать не знаю и почему так. это очень много.

Повторю совет начать использовать valgrind чем раньше, тем лучше, размер стека задаётся при помощи pthread_attr_setstacksize(), а мутексы можно сделать размером с int. Точнее, не классические мутексы, а с небольшим бузи-вейтом  - volatile int + атомарные бьюлтины  gcc  (compare_exchange и подобные)  + sched_yield(). Складывается впечатление, что у вас слишком большое количество мутексов.


"Размер процесса. Используемая память. Потоки."
Отправлено Fx , 15-Ноя-11 17:00 
> Повторю совет начать использовать valgrind чем раньше, тем лучше, размер стека задаётся
> при помощи pthread_attr_setstacksize(), а мутексы можно сделать размером с int. Точнее,
> не классические мутексы, а с небольшим бузи-вейтом  - volatile int
> + атомарные бьюлтины  gcc  (compare_exchange и подобные)  +
> sched_yield().

За совет с валгридом отдельное спасибо еще раз. Уже поставил новую ОС и валгрид, правда, если я правильно понул суть, то пока для своих целей использовать не получится: нужно переписать приложение, чтобы при завершении освобождало всю память (чтобы увидеть утечки)
Буду читать документацию.

> Складывается впечатление, что у вас слишком большое количество мутексов.

Два мутекса на объект-сессию для "человека". В принципе, можно до одного сократить, врятли один человек будет создавать одновременные запросы к демону.

По проблеме памяти и мутексов, ошибка, видимо в реализации мутексов под FreeBSD 6.1 или при компиляции gcc. потому что после перехода на FreeBSD 8.2 тот же код и база стартует занимая не 250 мегабайт, а 50мб (учитывая что часть этой памяти - это сами потоки). Хотя все равно мутекс не равен int*2(rw mutex), но уже приемлемо.

Да, к слову, может кому-то будет интересно, у меня по результатам получилось на FreeBSD 6.1, что мутексы не инициализированные занимают не много
    pthread_rwlock_t aMutex;
но как только инициализируешь каждый pthread_rwlock_init(&aMutex, NULL); - сразу память сжирается.

а константный инициализатор вообще не работает:
pthread_rwlock_t        rwlock1 = PTHREAD_RWLOCK_INITIALIZER;