#include <deque>
#include <list>
#include <string>
#include <queue>
#include"stdio.h"#include"conio.h"#include"windows.h"using namespace std;
struct Message
{
Message(const string& a, const string& b): A(a), B(b){}
string A,B;
};
int main(int argc, char* argv[])
{
int STRING_SIZE = 1000;
int TOTAL = 1000000;
int N = 1000;
if (argc > 1) N = atoi(argv[1]);
if (argc > 2) STRING_SIZE = atoi(argv[2]);
queue<Message*> z;
int k = 1;
printf("Portion size: %d, string size: %d, press ENTER to start\n", N, STRING_SIZE); getch();
string A(STRING_SIZE , '0');
string B(STRING_SIZE + STRING_SIZE , '1');
unsigned t = GetTickCount();
while (TOTAL > 0)
{
for (int i = 0; i < N; i++)
z.push(new Message(A,B));
while (!z.empty())
{
delete z.front();
z.pop();
}
printf("%d ", k);
k++;
TOTAL -= N;
}
printf(" done in %d ms", GetTickCount() - t); getch();
}
Идея очень проста — необходимо прокачать через очередь (STL queue) один миллион (TOTAL) неких сообщений (Message).
В queue мы храним только указатель (Message*). Новые объекты Message создаются и заносятся в очередь порциями.
Размер порции: N. То бишь заносим N новых сообщений, полностью выбираем их и уничтожаем и опять.
Подчеркиваю — после окончания прокачки сообщений ни одно сообщение не сохраняется — все уничтожены! То есть по идее мы должны выйти на то кол-во памяти, что было при запуске (ну ладно, пускай немного больше).
Итак, проблема: чем больше порция данных, тем больше памяти остается "не у дел" и не возвращается системе после окончания прокачки сообщений. Причем мне лично непонятно — кто и зачем взял эту память и не отдает. Ведь это явно не утечка, а какое-то внутреннее выделение под какие-то нужды.
Чтобы смотреть сколько памяти занято программой я использую Process Explorer от SysInternals. Открываем процесс, выбираем вкладку Performance Graph и смотрим Private Bytes.
Итак, запускаем программу вначале с порцией в тысячу сообщений:
queue.exe 1000
Сразу после запуска видимо, что занято 348 Kb. Жмем Enter и ждем окончания прокачки. Смотрим и видим, что теперь Private Bytes равно 3.7 Mb
Теперь порция в 10000:
queue.exe 10000
После окончания процесс занимает 24.5 Mb памяти!
Ну и дальше, как вы уже догадались, все хужее и хужее:
queue.exe 100000 — 68.7 Mb!!
Ну и наконец:
queue.exe 250000 — 156 Mb!!!
Шедевр! Кто бы мне объяснил — что происходит?
Я могу понять, что STL внутри себя выделяет память. Я не могу понять — почему эта память обратно не вернулась??
K>>Я могу понять, что STL внутри себя выделяет память. Я не могу понять — почему эта память обратно не вернулась??
D14>Смотреть на показания process explorer'a до того, как отработает деструктор очереди, не очень хорошая идея.
Я немного переделал пример — то же самое.
Переделал так — сначала прокачивается порциями по N, затем очередь уничтожается и прокачивается порциями по N/10 и затем очередь опять уничтожается. И затем смотрю память. Так вот: память все так же держится, но что интересно — во время второй прокачки память не растет. То есть действительно эта память потом используется...
K>>>Я могу понять, что STL внутри себя выделяет память. Я не могу понять — почему эта память обратно не вернулась?? D14>>Смотреть на показания process explorer'a до того, как отработает деструктор очереди, не очень хорошая идея. K>Я немного переделал пример — то же самое. K>Переделал так — сначала прокачивается порциями по N, затем очередь уничтожается и прокачивается порциями по N/10 и затем очередь опять уничтожается. И затем смотрю память. Так вот: память все так же держится,
не верю (с)
добавление z = queue<Message*>(); перед getch устраняет сей спецэффект, как и взятие всего кроме getch во вложенную область видимости.
Впрочем оно конечно может быть, не дело это таск манагером расход хипа тюнинговать.
Как много веселых ребят, и все делают велосипед...
Здравствуйте, Krovosos, Вы писали:
K>Я могу понять, что STL внутри себя выделяет память. Я не могу понять — почему эта память обратно не вернулась??
уважаемый дон когданить слышал про аллокаторы в stl?
я выкинул из примера все что связано с виндюками и прогнал под valgrind'ом, который в конце концов выдал мне следующее:
==3963== malloc/free: in use at exit: 0 bytes in 0 blocks.
==3963== malloc/free: 1,015,633 allocs, 1,015,633 frees, 24,004,650 bytes allocated.
==3963== For counts of detected errors, rerun with: -v
==3963== All heap blocks were freed -- no leaks are possible.
zaufi@zaufi /work/tests $ uname -a
Linux zaufi 2.6.30-gentoo-r4 #9 SMP PREEMPT Mon Aug 17 01:32:33 MSD 2009 x86_64 Intel(R) Core(TM)2 Duo CPU T7300 @ 2.00GHz GenuineIntel GNU/Linux
zaufi@zaufi /work/tests $ gcc --version
gcc (Gentoo 4.4.1 p1.0) 4.4.1
Copyright (C) 2009 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
дык вот возвращаясь к аллокаторам... рекомендую заглянуть в свою реализацию stl и посмотреть как работает дефолтный аллокатор... -- уверен откроете для себя много нового
K>>Я могу понять, что STL внутри себя выделяет память. Я не могу понять — почему эта память обратно не вернулась?? Z>уважаемый дон когданить слышал про аллокаторы в stl?
Z>я выкинул из примера все что связано с виндюками и прогнал под valgrind'ом, который в конце концов выдал мне следующее:
[...] Z>==3963== All heap blocks were freed -- no leaks are possible.
То бишь утечек не было...
Z>дык вот возвращаясь к аллокаторам... рекомендую заглянуть в свою реализацию stl и посмотреть как работает дефолтный аллокатор... -- уверен откроете для себя много нового
Ну я примерно представляю как он работает — он берет по мере надобности большие куски памяти у ОС и устраивает на них хипы. Разве нет?
И после выделения и удаления большого числа объектов память не возвращается системе потому что:
a) она сильно дефрагментирована;
b) никто и не собирался возвращать системе выделенные по хипы блоки памяти.
PS В windows есть вызов _heapmin(), который должен вернуть память хипа системе — не помог.
K>>>Я могу понять, что STL внутри себя выделяет память. Я не могу понять — почему эта память обратно не вернулась?? Z>>уважаемый дон когданить слышал про аллокаторы в stl?
Z>>я выкинул из примера все что связано с виндюками и прогнал под valgrind'ом, который в конце концов выдал мне следующее: K>[...] Z>>==3963== All heap blocks were freed -- no leaks are possible.
K>То бишь утечек не было...
Z>>дык вот возвращаясь к аллокаторам... рекомендую заглянуть в свою реализацию stl и посмотреть как работает дефолтный аллокатор... -- уверен откроете для себя много нового
K>Ну я примерно представляю как он работает — он берет по мере надобности большие куски памяти у ОС и устраивает на них хипы. Разве нет?
K>И после выделения и удаления большого числа объектов память не возвращается системе потому что: K>a) она сильно дефрагментирована; K>b) никто и не собирался возвращать системе выделенные по хипы блоки памяти.
K>PS В windows есть вызов _heapmin(), который должен вернуть память хипа системе — не помог.
Гриша, выньдовс реально память освобожденную память не покажет, пока не было попыток ей воспользоваться. Страницы маркируются как свободные, но относящиеся к процессу. Запусти рядом процесс жадный до памяти и ты увидишь, как освободится память.
Единственный разумный выход — свой аллокатор памяти. STLport я попробовал, с разными настройками и результат почти такой же. Лучшими были настройки по умолчанию, но все равно 71 МБайт памяти остался выделен программе.
Приходит в голову только свой аллокатор, который берет большие куски и размещает на них сообщения, а потом уплотняет и пустые куски возвращает системе...
A>Гриша, выньдовс реально память освобожденную память не покажет, пока не было попыток ей воспользоваться. Страницы маркируются как свободные, но относящиеся к процессу. Запусти рядом процесс жадный до памяти и ты увидишь, как освободится память.
K>Единственный разумный выход — свой аллокатор памяти. STLport я попробовал, с разными настройками и результат почти такой же. Лучшими были настройки по умолчанию, но все равно 71 МБайт памяти остался выделен программе.
K>Приходит в голову только свой аллокатор, который берет большие куски и размещает на них сообщения, а потом уплотняет и пустые куски возвращает системе...
Эхх... Вы под Win XP гоняете? Попробуйте тогда минимайзнуть окно вашей программы и посмотреть в Task Manager. Удивитесь.