Хотя я думаю, что он, возможно, немного преувеличивает ситуацию, я в целом согласен с выводом DeadMG о том, что то, что вы делаете, вызывает проблемы.
Хотя я, как правило, выгляжуat (что бы ни сделал кто-нибудь) и говоря «не делай этого, просто используй вектор», этот случай вполне может быть исключением.Вы создаете огромное количество объектов, которые должны быть крошечными.К сожалению, вектор обычно выглядит примерно так:
template <class T>
class vector {
T *data;
size_t allocated;
size_t valid;
public:
// ...
};
На типичной 32-битной машине это уже двенадцать байтов.Поскольку вы используете vector<vector<char> >
, у вас будет 12 байтов для внешнего вектора, плюс еще двенадцать для каждого вектора, который он содержит.Затем, когда вы на самом деле сохраняете какие-либо данные в своих векторах, каждому из них необходимо выделить блок памяти из свободного хранилища.В зависимости от того, как реализован ваш бесплатный магазин, у вас обычно будет минимальный размер блока - часто 32 или даже 64 байта.Хуже того, куча, как правило, имеет свои собственные издержки, поэтому она добавляет больше памяти в каждый блок для своего собственного учета (например, она может использовать связанный список блоков, добавляя другойстоимость указателя данных для каждого распределения).
Только для осмыслений, давайте предположим, что вы усредняете четыре вектора по четыре байта за штуку, и что ваш менеджер кучи имеет минимальный размер блока 32 байта и один дополнительный указатель (или int) для его учета (давая реальный минимум 36 байтов на блок).Умножая это, я получаю 204 байта за штуку - достаточно близко к вашим 209, чтобы верить, что это достаточно близко к тому, с чем вы имеете дело.
В этот момент вопрос состоит в том, как решить проблему.Одна из возможностей - попытаться работать за кулисами.Все контейнеры в стандартной библиотеке используют распределители, чтобы получить их память.Хотя они по умолчанию распределитель получает память непосредственно из бесплатного хранилища, вы можете заменить другой, если вы выберете.Если вы немного осмотритесь, то сможете найти любое количество альтернативных распределителей, многие / большинство из которых должны помочь именно в той ситуации, в которой вы находитесь - уменьшая потерянную память при выделении большого количества мелких объектов.Пара, на которую стоит обратить внимание, - это Boost Pool Allocator и Loki маленький объектный распределитель.
Другая возможность (которая может быть объединена с первой) - это вообще отказаться от использования vector<vector<char> >
и заменить егос чем-то вроде:
char partitions[16];
struct parts {
int part0 : 4;
int part1 : 4;
int part2 : 4;
int part3 : 4;
int part4 : 4;
int part5 : 4;
int part6 : 4
int part7 : 4;
};
На данный момент я предполагаю, что максимум 8 разделов - если это может быть 16, вы можете добавить больше к parts
.Это, вероятно, должно немного уменьшить использование памяти, но (как есть) повлияет на ваш другой код.Вы также можете заключить это в небольшой собственный класс, который обеспечивает адресацию в стиле 2D, чтобы минимизировать влияние на остальную часть вашего кода.