2017-01-04 2 views
5

사용자가 1 백만 단어로 구성된 거대한 파일을 업로드합니다. 파일을 구문 분석하고 파일의 각 줄을 LinkedHashMap<Integer, String>에 넣습니다.LinkedHashMap 메모리 사용량

키로 O (1) 액세스 및 제거가 필요합니다. 또한 액세스 순서를 유지하고 위치와 정렬을 반복해야합니다.

메모리 소비가 많습니다. Java 8에 나타나는 Strings deduplication feature을 활성화했지만 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는 3 배 이상을 차지합니다. 나는 왜 OP가 이것이 필요한지 알고 싶어한다. – Michael

+1

소스를 탐색 할 때 너무 빠릅니다. 그 엔트리는 4 개의 필드가 더있는'HashMap.Node'에서 상속받습니다. 추가로 [object headers] (http://stackoverflow.com/q/26357186)의 크기가 구현 세부 사항입니다. – glee8e

답변

1

?

1) JVM 시작에 -XX:+UseCompressedOops 플래그를 추가하십시오.

2) 귀하의 필요에 맞게 최적화 된 LinkedHashMap 버전을 구현하십시오. I. e. 원래 intInteger 대신 키로 사용하고, 필요하지 않으면 "이전"포인터를 제거하십시오. OpenJDK가 GPLv2 라이센스이므로 GPLv2 라이센스 하에서 수정 된 해시 맵 구현을 해제하지 않는 한 OpenJDK 소스 복사가 불가능할 수 있습니다 GPLv2. 그러나 Apache 라이센스이므로 LinkedHashMap 구현을 Android Open Source Project에서 복사하고 수정할 수 있습니다.