QHash хранит большое количество данных

У меня есть 10 000 000 записей типа struct{int, int, int, int}. когда я сохраняю их с помощью QHash или QMap, он занимает много памяти, на самом деле это должно занять около

10,000,000 * 4 * 4 (sizeof integer) <= 153 MB

но когда я загружаю свои данные, для QHash и QMap требуется около 1,2 ГБ, почему это происходит и как я могу оптимизировать их как для скорости, так и для памяти? (с помощью любой другой структуры данных или некоторых трюков с qmap и qhash)


person abdolahS    schedule 17.05.2017    source источник
comment
QHash и QMap являются ассоциативными контейнерами: если предположить, что ваша структура из 4-х целых чисел является хранимым значением, каков тип ключей?   -  person rgmt    schedule 17.05.2017
comment
Ключи @wasthishelpful — это четыре других целых числа, которые я сохраняю с помощью QtPrivate::QHashCombine для qhash().   -  person abdolahS    schedule 17.05.2017
comment
Вероятно, это будет близко к 153 МБ, если это последовательный массив, но карты имеют дополнительные накладные расходы на структуру данных и накладные расходы на выделение кучи. Но все равно не должно быть так много.   -  person dtech    schedule 17.05.2017
comment
Как вы измеряете потребление памяти? И как добавлять элементы? Попробуйте использовать: yourqhash.reserve(maxsize); перед добавлением элементов и посмотрите, что произойдет.   -  person Zlatomir    schedule 17.05.2017
comment
Да, политики резервирования памяти довольно щедры по мере увеличения количества элементов в контейнере. Они пропорциональны, не уменьшаются по мере увеличения количества элементов.   -  person dtech    schedule 17.05.2017


Ответы (1)


Вы сказали в комментарии, что используете еще четыре целых числа в качестве ключа - эти значения также должны быть сохранены, поэтому вы фактически сохраняете 8 целых чисел, а не 4. Кроме того, QHash должен хранить значение хэша для эффективно искать значения на основе ключа. Хэш представляет собой целое число без знака, поэтому у вас есть 9 значений, каждое из которых имеет длину 4 байта. В сумме получается ~350 МБ.

Кроме того, внутренне QHash или QMap могут использовать некоторые отступы между своими элементами, например, для удовлетворения требования к выравниванию структуры данных. Заполнение — это множитель 1 байта, а это значит, что при 10 млн элементов мы можем получить минимум несколько десятков дополнительных мегабайт.

Кроме того, QHash и QMap — это не просто необработанные данные — они оба используют дополнительные указатели на свои внутренние структуры данных и т. д., что является еще одной причиной, по которой одна запись займет больше времени. пространство, чем вы ожидали.

Еще одним источником увеличения размера данных может быть тот факт, что по соображениям эффективности эти классы могут хранить некоторые дополнительные значения, чтобы они предварительно вычислялись при вызове некоторых из их методов.

И последнее, но не менее важное: QHash резервирует больше памяти, чем требуется его текущим элементам в любой момент по соображениям эффективности (избегая ненужного копирования). Я ожидаю, что чем больше размер, тем больше памяти он будет резервировать на всякий случай, потому что копирование становится дороже. Вы можете заранее проверить зарезервированную память, вызвав метод capacity(). Если вы хотите ограничить объем зарезервированной памяти, вызовите метод squeeze(), чтобы настроить объем памяти таким образом, чтобы ее было достаточно для хранения текущих сохраненных элементов.

person KjMag    schedule 17.05.2017
comment
Вместо использования squeeze лучше использовать reserve, потому что он знает количество элементов. - person Zlatomir; 18.05.2017
comment
Если вы вызываете backup(), а затем вставляете элементы, реализация может зарезервировать больше места во время процесса вставки, так что вы все равно можете вызвать в конце сжатие(), просто чтобы быть уверенным. - person KjMag; 18.05.2017