База данных содержит 100.000 записей. Каждую запись считываю в обьект CRecObj.
Обьект помещаю в std::vector<CRecObj>, используя push_back. Смотрю размер CRecObj через sizeof(CObj) —
примерно около 80 байт каждый. Размер вектора получается в итоге 5 Мб.
А оперативной памяти сьедает более 100 МБ. В чем дело? И как
с этим справится?
G>База данных содержит 100.000 записей. Каждую запись считываю в обьект CRecObj. G>Обьект помещаю в std::vector<CRecObj>, используя push_back. Смотрю размер CRecObj через sizeof(CObj) — G>примерно около 80 байт каждый. Размер вектора получается в итоге 5 Мб. G>А оперативной памяти сьедает более 100 МБ. В чем дело? И как G>с этим справится?
Приведите определение CRecObj. Почти уверен что у вас там есть члены содержащие динамически выделенную память которая sizeof'ом не учитывается.
Здравствуйте, gepard1980, Вы писали:
G>База данных содержит 100.000 записей. Каждую запись считываю в обьект CRecObj. G>Обьект помещаю в std::vector<CRecObj>, используя push_back. Смотрю размер CRecObj через sizeof(CObj) — G>примерно около 80 байт каждый. Размер вектора получается в итоге 5 Мб. G>А оперативной памяти сьедает более 100 МБ. В чем дело? И как G>с этим справится?
1) В вектор лучше данные такого обьема не закидать потому что он много операций с памятью проводит(при ресайзе особенно). Лучше использовать указатели на те обьекты.
2) Вектор не обязательно держит столько памяти, сколько Вы его попросили. Он выделяет еще немного "для запаса". Причем немного может быть совсем немлаленьким числом.
G>База данных содержит 100.000 записей. Каждую запись считываю в обьект CRecObj. G>Обьект помещаю в std::vector<CRecObj>, используя push_back. Смотрю размер CRecObj через sizeof(CObj) — G>примерно около 80 байт каждый. Размер вектора получается в итоге 5 Мб. G>А оперативной памяти сьедает более 100 МБ. В чем дело? И как G>с этим справится?
ну как вариант -- попробовать сделать вектору reserve() перед циклом.
тогда push_back не будет приводить к переаллокации памяти.
И что значит "съедает 100 МБ"? как именно мерялось?
Здравствуйте, gepard1980, Вы писали:
G>Размер вектора получается в итоге 5 Мб.
Через size смотрели? G>А оперативной памяти сьедает более 100 МБ. В чем дело? И как G>с этим справится?
Проверьте capacity, 100 ли там Мб?
Здравствуйте, VoidEx, Вы писали:
VE>Здравствуйте, gepard1980, Вы писали:
G>>Размер вектора получается в итоге 5 Мб. VE>Через size смотрели?
Да размер(примерный 80 байт) элемента на количество элементов в векторе.
G>>А оперативной памяти сьедает более 100 МБ. В чем дело? И как G>>с этим справится? VE>Проверьте capacity, 100 ли там Мб?
Ну вот, как раз то, о чем и говорил Аноним 639. CString — это всего навсего умная обертка над указателем. Она имеет фиксирванный (сравнительно небольшой) размер. Размеры текстовых данных, адресуемых объектами типа CString, не учитывываются оператором sizeof. Вероятно, именно эти текстовые данные и занимают бОльшую часть занимаемой памяти.
--
Справедливость выше закона. А человечность выше справедливости.
Здравствуйте, gepard1980, Вы писали:
VE>>Проверьте capacity, 100 ли там Мб?
G>Capacity показывает 109500.
Т.е. элементов 100000, а реально выделенной памяти на 109500.
А столько памяти отнимает то, что CString — обёртка над указателем, которая сама указывает на кусок памяти, о чём Вам написали выше.
разер памяти занятой под CRecObj будет равен не sizeof(CRecObj), а
sizeof(CRecObj) + размер памяти выделенной s1 + размер памяти выделенной s2 + размер памяти выделенной s3
Чтобы точно определить размер дополнительной памяти занятой CString'ом документированных путей нету. Но ориентировочно оно будет от одного до двух размеров хранящейся строки. Умножить в 2 раза если определен UNICODE.
Здравствуйте, Sealcon190, Вы писали:
S>Здравствуйте, gepard1980, Вы писали:
G>>Обьект помещаю в std::vector<CRecObj>, используя push_back.
S>
а что такого? Cstring наверняка copyonwrite использует, в результате копируется 80 байт на одно копирование структуры.
если этот вектор по значению не передавать везде, то тормозов даже видно не будет. зато не нужно рулить памятью, мучаясь с указателями, или объяснять gepard1980-у что такое умные указатели и какие подводные камни встречаются при их использовании.
Здравствуйте, gepard1980, Вы писали:
G>База данных содержит 100.000 записей. Каждую запись считываю в обьект CRecObj. G>Обьект помещаю в std::vector<CRecObj>, используя push_back. Смотрю размер CRecObj через sizeof(CObj) — G>примерно около 80 байт каждый. Размер вектора получается в итоге 5 Мб. G>А оперативной памяти сьедает более 100 МБ. В чем дело? И как G>с этим справится?
Здравствуйте, VoidEx, Вы писали:
VE>Здравствуйте, gepard1980, Вы писали:
G>>Размер вектора получается в итоге 5 Мб. VE>Через size смотрели? G>>А оперативной памяти сьедает более 100 МБ. В чем дело? И как G>>с этим справится? VE>Проверьте capacity, 100 ли там Мб?
Здравствуйте, Sealcon190, Вы писали:
S>Здравствуйте, dotidot, Вы писали:
D>>а что такого?
S>Да ничего. Но я бы расстреливал всех кто для вектора использует push_back.
Для push_back сложность вставки определена как 'amortized constant time'. Это значит, что вставка N элементов происходит за O(N) времени, но нет гарантий, что вставка одного элемента произойдет за O(1).
Если количество элементов известно, то для вставки одного элемента можно добиться O(1), вынеся факторы, которые делают эту сложность амортизированной вне push_back. Другими словами — производить выделение памяти заранее.
Для алгоритмов, в которых суммарное количество вставляемых элементов заранее неизвестно, использование push_back — практически единственный выход, и других, принципиально иных, сценариев для вставки в vector нет.
Варианты с изменением типа контейнера можно рассматривать только после выявления типичных сценариев использования.
Использование контейнеров, которые предполагают динамическое выделение памяти (множество мелких объектов в таких масштабах) помимо очевидных преимуществ может привести к таким неприятным последствиям, как дефрагментация кучи, слишком частые блокировки стандартного менеджера памяти в многопоточном окружении (при каждой вставке), плохая локальность данных и т.д. А может и не привести. Смотреть надо...