2017-01-04 2 views
5

Пользователь загружает огромный файл, состоящий из 1 миллиона слов. Я разбираю файл и помещаю каждую строку файла в LinkedHashMap<Integer, String>.Расход памяти LinkedHashMap

Мне нужен O (1) доступ и удаление ключом. Кроме того, мне нужно сохранить порядок доступа, перебирать из любой позиции и сортировать.

Потребление памяти огромно. Я включил Strings deduplication feature, который появляется в Java 8, но оказывается, что LinkedHashMap потребляет большую часть памяти.

Я обнаружил, что LinkedHashMap.Entryconsumes 40 bytes, но есть только 2 указателя - один для следующей записи и один для предыдущей записи. Я думал, что 1 указатель должен быть 64 бит или 32 бита. Покупайте, если я делю 409,405,320 (байт) на 6 823 422 (количество записей). У меня есть 60 байт на запись.

Я думаю, что мне не нужен предыдущий указатель, следующий указатель должен быть достаточным для поддержания порядка. Почему LinkedHashMap потребляет столько памяти? Как уменьшить потребление памяти?

Instance occurence

+0

Возможно ли, что оболочка Integer использует столько дополнительной памяти? Возможно, [реализация на основе int] (https://github.com/ggrandes/kvstore/blob/master/src/main/java/org/javastack/kvstore/structures/hash/IntLinkedHashMap.java) может помочь – Moira

+1

@ 1blustone Если вы посмотрите на изображение, вы увидите, что 'Integer' занимает 16% кучи. 'LinkedHashMap.Entry's занимают более 3-х раз. Я считаю, что ОП хочет знать, почему это должно быть так. – Michael

+1

Вы слишком быстро просматриваете источники. эта запись наследуется от 'HashMap.Node', которая имеет еще 4 поля, и есть дополнительные [заголовки объектов] (http://stackoverflow.com/q/26357186), размер которых является просто детализацией реализации. – glee8e

ответ

1

Как сократить потребление памяти?

1) Добавить -XX:+UseCompressedOops флаг к вашему запуску JVM.

2) Внесите свою собственную версию LinkedHashMap, оптимизированную для ваших нужд. I. e. используйте примитив int в качестве ключа вместо Integer, удалите «предыдущий» указатель, если он вам не нужен, и т. д. Обратите внимание, что копирование источника OpenJDK может быть невозможным, если вы не хотите опубликовать свою модифицированную реализацию хеш-карты под лицензией GPLv2, поскольку OpenJDK GPLv2. Однако вы можете копировать и изменять реализацию LinkedHashMap из Android Open Source Project, потому что это лицензия на Apache.