2017-01-04 6 views
5

L'utilisateur télécharge un fichier volumineux de 1 million de mots. J'analyse le fichier et place chaque ligne du fichier dans un LinkedHashMap<Integer, String>.Consommation de mémoire LinkedHashMap

J'ai besoin de O (1) accès et retrait par clé. De plus, j'ai besoin de conserver l'ordre d'accès, de parcourir n'importe quelle position et trier.

La consommation de mémoire est énorme. J'ai activé Strings deduplication feature qui apparaît dans Java 8, mais il s'avère que le LinkedHashMap consomme la majeure partie de la mémoire.

J'ai trouvé que LinkedHashMap.Entryconsumes 40 bytes, mais il n'y a que 2 pointeurs - un pour l'entrée suivante et un pour l'entrée précédente. Je pensais que 1 pointeur devrait être 64 bits ou 32 bits. Acheter si je divise 409 405 320 (octets) par 6 823 422 (nombre d'entrées) J'ai 60 octets par entrée.

Je pense que je n'ai pas besoin du pointeur précédent, le pointeur suivant devrait être suffisant pour garder l'ordre. Pourquoi LinkedHashMap consomme-t-il autant de mémoire? Comment puis-je réduire la consommation de mémoire?

Instance occurence

+0

Est-il possible que le wrapper 'Integer' utilise beaucoup plus de mémoire? Peut-être qu'une implémentation ['int'] (https://github.com/ggrandes/kvstore/blob/master/src/main/java/org/javastack/kvstore/structures/hash/IntLinkedHashMap.java) pourrait aider – Moira

+1

@ 1blustone Si vous regardez l'image, vous pouvez voir que 'Integer's occupent 16% du tas. 'LinkedHashMap.Entry's prennent plus de 3 fois plus. Je crois que le PO veut savoir pourquoi cela devrait être le cas. – Michael

+1

Vous parcourez trop rapidement les sources. cette entrée hérite de 'HashMap.Node' qui a 4 champs de plus, et il y a des [en-têtes d'objet] supplémentaires (http://stackoverflow.com/q/26357186) dont la taille est juste un détail d'implémentation. – glee8e

Répondre

1

Comment réduire la consommation de mémoire?

1) Ajoutez le flag -XX:+UseCompressedOops à votre démarrage JVM.

2) Implémentez votre propre version de LinkedHashMap, optimisée pour vos besoins. C'est à dire. utilisez la primitive int comme clé au lieu de Integer, supprimez le pointeur "précédent" si vous n'en avez pas besoin, etc. Notez que la copie de source OpenJDK peut être impossible à moins que vous souhaitiez libérer votre implémentation de mappe de hachage modifiée sous licence GPLv2, car OpenJDK est GPLv2. Cependant, vous pouvez copier et modifier l'implémentation de LinkedHashMap à partir d'Android Open Source Project, car il s'agit d'une licence Apache.