Вопрос про распределение памяти в Windows NT

Все, что вы хотели знать о программизме, но боялись спросить.
Ответить
Michael
Частый Гость
Сообщения: 26
Зарегистрирован: 17 фев 2003, 19:06
Контактная информация:

Вопрос про распределение памяти в Windows NT

Сообщение Michael »

Есть консольное приложение, которое в цикле кроме прочего выделяет и освобождает память. Смотрю в таск менеджере - кол-во памяти, закрепленное за приложением, растет. Но, мемори ликов нет - 100%. Минимизирую приложение - объем памяти резко уменьшается. Консоль - ничего в ней при минимизации не делается (впрочем, в GUI то же самое). Максимизирую - снова растет. Наверно, NT учитывает всю память, которую приложение отдало и резервирует ее в надежде, что оно ее еще затребует?

Вроде бы, ничего страшного, но проблема такая:
Спустя какое-то время, когда объем памяти приложения вырастает значительно (200 MB при ОЗУ 1GB) прога начинает тормозить и CPU usage увеличивается. Где-то % на 20 выполняется медленнее (память фрагментирована в NT?). Минимизирую (NT думает пару секунд) - все возвращается в норму и память уменьшается до ~30 MB, в 7 раз. Потом все повторяется снова.

Вопрос - как с этим бороться?

NT4 SP6a, VC++ SP5, если это важно.

SetProcessWorkingSetSize() - не поможет, случайно? Сейчас наткнулся.
dEBUGER
Частый Гость
Сообщения: 23
Зарегистрирован: 26 фев 2003, 15:01
Откуда: Toronto

Сообщение dEBUGER »

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

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

Решать надо кардинально - сделать несложный пул памяти, отхватить его в начале (до цикла) и в цикле выделять-освобождать память из пула.
Michael
Частый Гость
Сообщения: 26
Зарегистрирован: 17 фев 2003, 19:06
Контактная информация:

Сообщение Michael »

Не могу я так делать, как ты говоришь. Даже если менеджер памяти напишу, который писать не хочу. Мне в прогу приходят изображения (большие) из которых я выделяю разное кол-во кусков разных размеров в зависимости от того, что там, с помощью 3rd party image analysis либы, которая отвечает за выделение памяти для этих блоков. Короче, я только handle на блок из нее получаю. И сказать ей, откуда брать память, не могу. Могу только handle удалить потом, что и делаю.
Michael
Частый Гость
Сообщения: 26
Зарегистрирован: 17 фев 2003, 19:06
Контактная информация:

Сообщение Michael »

Вот еще одно проявление проблемы, скорее всего с тем, как в программе выделяется память, не связанное.

Два компа - первый постоянно хватает изображение в цикле и шлет его другому.
Второй принимает изображение в заранее в начале работы созданный буфер, и выводит его на экран.

Если первый компьютер (посылающий данные) медленнее первого, все работает ОК часами.
Если первый компьютер быстрее (или одинаковый), то второй компьютер начинает через нек-рое время тормозить, memory and CPU usage растет. Минимизирую прогу на втором - все восстанавливается на время.

Скорее всего никаких временных буферов там не выделяется, на втором, завтра точно проверю. Подозрение на внутренние TCP/IP буферы windows, которые при большой загрузке она не успевает чистить и память становится фрагментированной. До swap дело не доходит, памяти куча.
Аватара пользователя
ajkj3em
Маньяк
Сообщения: 2063
Зарегистрирован: 12 ноя 2006, 06:53

Сообщение ajkj3em »

Michael писал(а):Подозрение на внутренние TCP/IP буферы windows, которые при большой загрузке она не успевает чистить и память становится фрагментированной.
нет, не там копаешь. размеры этих буферов выставляются через setsockopt(SOL_SOCKET, SO_xxxBUF, ...).

я видел похожее поведение - прога была немного из другой области, она активно писала на диск и там тоже каким-то образом росло количество используемой прогой памяти хотя в коде ничего такого небыло (тоже под nt). разрешить это удалось таки путем плясок с бубнами вокруг WRITETHROUGH и NOBUFFERING для файл handle. но попытки найти чего-либо в инете на эту тему *ничего* не дали - проблема похоже была известная, но причин никто не знал :-/
Аватара пользователя
ajkj3em
Маньяк
Сообщения: 2063
Зарегистрирован: 12 ноя 2006, 06:53

Сообщение ajkj3em »

да и фрагментация памяти под операционками с paged memory support -
маловероятна. unless memory manager совсем криво написан ...

я бы еще посмотрел на твою 3rd party либу повнимательнее (это кстати не ipl часом ?). если либа кошерная, то она должна иметь memory allocation hooks или типа того. если либа бинарная, то имеет смысл проверить ге завязана ли она на msvcrtD ... короче, выяснишь - свисти :)
Аватара пользователя
Lepsik
Житель
Сообщения: 522
Зарегистрирован: 17 фев 2003, 18:34
Откуда: Berlin
Контактная информация:

Сообщение Lepsik »

huh писал(а):да и фрагментация памяти под операционками с paged memory support -
маловероятна. unless memory manager совсем криво написан ...
я раз столкнулся - педределывал прогу за товарищем - он выделял
в цикле блоки, размер каждого в цикле рос. В результате каждый выделенный блок получался больше освобожденных .
В реальной жизни это не страшно - но когда выделяешь под задачу 300 мег, то 500 мег не хватало и задача умерала в свопинге.

однакратное выделение в начале свело вычисления с 20 часов до 1 часа.


Кстати, Michael-ской проге лучше тоже держать максимальный обьем буфера. 20-30 мег по прогу никого щас не удивит, а жизнь облегчит
Michael
Частый Гость
Сообщения: 26
Зарегистрирован: 17 фев 2003, 19:06
Контактная информация:

Сообщение Michael »

2huh: Используем мы Matrox MIL library 7.0 для image analysis. Да, можно там ей свою память подсунуть для буфера. Но больно уж много кода менять придется. Плюс у нас в framework память выделяется, не так просто сейчас уже свой memory manager писать. Нет проще пути? Попробую SetProcessWorkingSetSize еще.

Но, главное, что во втором случае, когда программа просто получает картинки и отображает, выделения памяти в цикле не происходит, все принимается в тот же буфер. А объем памяти все равно растет в принимающем процессе и программа тормозит, 100% cpu usage. Задержка между тем, что захватывается и тем, что показывается, увеличивается. Это если принимающий и передающий процессоры одинаковые. Если передающий медленнее - все ОК.

Там такая ситуация: принимающий TCP/IP тред независим от отображающего на экране и в принипе может принимать чаще, чем тот отображает. Но принимает-то он в тот же буфер. Единственное место, где может память расти в программе - это очередь сообщений отображающего треда. Но она растет совсем незначительно по сравнению с объемом передаваемого изображения - 2 MB. Хоть huh и говорит, что не бывает, а все-равно кажется, что TCP/IP где-то данные накапливает, так как объем памяти растет примерно на эти 2 MB в секунду.

У нас overlapped I/O для сокетов используется. Создается event на сокет, буфер 8 KB, и ждутся эвенты после WSARecv(). Сокет тот же, буфер тот же, соединение не рвется. Так что, не знаю, на что и думать тут. thread priority отображающего треда могу поднять, синхронизацию дополнительную с передающим компом ввести, но как-то криво это.
Есть еще идеи?
Boo
Пользователь
Сообщения: 92
Зарегистрирован: 20 фев 2003, 00:41

Re: Вопрос про распределение памяти в Windows NT

Сообщение Boo »

Michael писал(а):Смотрю в таск менеджере - кол-во памяти, закрепленное за приложением, растет. Но, мемори ликов нет - 100%. Минимизирую приложение - объем памяти резко уменьшается. Консоль - ничего в ней при минимизации не делается (впрочем, в GUI то же самое).
смотреть в таск менеджер - это неправильно. надо смотреть в перфмон, каунтер "private bytes". если этот каунтер растет, значит есть лики. таск менеджер показывает именно working set, что с ликами не очень связано.

а еще вопрос: как память выделяется? malloc/HeapAlloc/VirtualAlloc/new или еще как?

минимизация консоли теоретически может приводить к тому что система перестает выделять память на отрисовку, поэтому потребление падает.
Michael
Частый Гость
Сообщения: 26
Зарегистрирован: 17 фев 2003, 19:06
Контактная информация:

Сообщение Michael »

А звать _heapmin после каждого освобождения памяти не пробовали?
не пробовали пока. Попробую.
еще вопрос: как память выделяется? malloc/HeapAlloc/VirtualAlloc/new или еще как?
У нас по new только. MIL не знаю как выделяет. Но, если MIL не выделяет (да и мы, похоже, только пакеты по сети приходят на то же место), тоже растет.
минимизация консоли теоретически может приводить к тому что система перестает выделять память на отрисовку, поэтому потребление падает.
С 200 MB в 10 раз? Да мне не важно, что task manager пишет, главное, чтоб программа не начинала тормозить.
Ответить