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)
1 ответ
Вы сказали в комментарии, что вы используете еще четыре целых числа в качестве ключа - эти значения также должны быть сохранены, так что вы на самом деле сохраняете 8, а не 4. Кроме этого, QHash должен хранить значение хеша в эффективно искать значения на основе ключа. Хеш - это целое число без знака, поэтому у вас есть 9 значений, каждое длиной 4 байта. Суммируется до ~350 МБ.
Кроме того, внутренне QHash или QMap могут использовать некоторые отступы между своими элементами, например, для удовлетворения требований выравнивания структуры данных. Заполнение является множителем 1 байта, что означает, что в случае 10 млн элементов мы можем получить как минимум несколько десятков дополнительных мегабайт.
Кроме того, QHash и QMap - это не просто необработанные данные - они оба используют дополнительные указатели на свои внутренние структуры данных и т. Д., Что является еще одной причиной, почему одна запись займет больше места, чем вы ожидали.
Другим источником увеличения объема данных может быть тот факт, что по причинам эффективности эти классы могут хранить некоторые дополнительные значения, чтобы они были предварительно вычислены при вызове некоторых из их методов.
И последнее, но не менее важное: QHash резервирует больше памяти, чем нужно его текущим элементам в любой данный момент из соображений эффективности (избегая ненужного копирования). Я ожидаю, что чем больше размер, тем больше памяти он будет резервировать на всякий случай, потому что копирование обходится дороже. Вы можете проверить заранее зарезервированную память, вызвав метод acity(). Если вы хотите ограничить объем зарезервированной памяти, вызовите метод squeeze(), чтобы настроить память так, чтобы ее было достаточно для хранения сохраненных в данный момент элементов.