"고전적인"HashMap과 비교하여 ConcurrentHashMap의 메모리 오버 헤드를 아는 사람이 있습니까?ConcurrentHashMap 메모리 오버 헤드
- 시공 중입니까?
- 요소 삽입시?
"고전적인"HashMap과 비교하여 ConcurrentHashMap의 메모리 오버 헤드를 아는 사람이 있습니까?ConcurrentHashMap 메모리 오버 헤드
64 비트 JVM에서 -XX:-UseTLAB -XX:NewSize=900m -mx1g
과 함께 다음을 실행하는 경우.
public static void main(String... args) throws NoSuchMethodException, IllegalAccessException {
for (int i = 0; i < 4; i++) {
long used1 = usedMemory();
populate(new HashMap());
long used2 = usedMemory();
populate(new ConcurrentHashMap());
long used3 = usedMemory();
System.out.println("The ratio of used memory is " + (double) (used3 - used2)/(used2 - used1));
System.out.println("For an extra " + ((used3 - used2) - (used2 - used1))/1000000 + " bytes per entry was used.");
}
}
private static void populate(Map map) {
for (Integer i = 0; i < 1000000; i++)
map.put(i, i);
}
private static long usedMemory() {
return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
}
1 백만 항목의 Java 6 및 7이 제공됩니다.
The ratio of used memory is 1.1291128466982379
For an extra 8 bytes per entry was used.
The ratio of used memory is 1.1292086928728067
For an extra 8 bytes per entry was used.
The ratio of used memory is 1.1292086928728067
For an extra 8 bytes per entry was used.
The ratio of used memory is 1.1292086928728067
For an extra 8 bytes per entry was used.
8MB의 메모리 비용은 약 5 센트입니다.
나는이 질문의 전제를 이해하지 못한다. 동시성이 필요하거나 그렇지 않다.
그러나 this link에 따르면 빈 ConcurrentHashMap
의 메모리 풋 프린트는 1700 바이트입니다. 읽기/쓰기 액세스가 필요한 여러 스레드가있는 경우 ConcurrentHashMap
을 사용하는 것이 좋지만 읽기 액세스가 필요한 많은 스레드가 있지만 쓰기가있는 스레드가 많은 경우 Hashtable
을 사용하는 것이 좋습니다.
ConcurrentHashMap
은 건설 및 삽입시 모두 HashMap
보다 훨씬 많은 메모리를 사용하지 않습니다. 초기화 데이터
ConcurrentHashMap
에서
은 HashMap과 같이 메모리의 거의 같은 양 사용하고, 별도의 부기 변수 잠금 커플 약간 이상일 수있다.
초기화 중에 ConcurrentHashMap
은 16 개의 세그먼트를 만들어 키 - 값을 저장하며 각 세그먼트는 HashMap과 동일합니다.
각 세그먼트의 초기 용량/크기는 전체 초기 용량의 1/16입니다. 따라서 본질적으로 ConcurrentHashMap
은 하나의 HashMap에 해당하는 16 개의 작은 HashMaps를 생성합니다. 각 세그먼트에는 자체 잠금 및 장부 보관 변수 (개수, 임계 값 등)가 있습니다. 이는 여분의 메모리 오버 헤드입니다.
당신은 ConcurrentHashMap
에 의 concurrencyLevel 매개 변수에 적절한 값을 전달하여 ConcurrentHashMap
에 의해 만들어진 세그먼트의 수를 제어 할 수 있습니다. 이 값이 작 으면 사용되는 공간은 적지 만 많은 수의 스레드가 맵을 업데이트하면 더 많은 경합이 발생합니다. 이 값이 높을수록 세그먼트가 더 많이 생성되지만 병렬 업데이트의 성능은 더 빠릅니다. 참고 : concurrencyLevel 매개 변수의 값이 현저히 높으면 공간과 시간에 모두 영향을줍니다.
메모리의이 작은 오버 헤드는 개발자가 동시성에 대한 대가로 기꺼이 받아 들일 수있는 것입니다. 삽입 세그먼트가 작성 얻을
에서
는, 그 세그먼트의 크기가 증가됩니다. 크기를 늘리는 정책은 HashMap과 동일합니다. loadfactor 매개 변수는 세그먼트의 크기를 늘릴시기를 결정합니다. 채워지는 세그먼트 만 증가합니다.다시 한번, 메모리 오버 헤드는 HashMap과 거의 같습니다.
전체적으로 ConcurrentHashMap
은 HashMap
보다 훨씬 많은 메모리를 사용하지 않지만, ConcurrentHashMap
에서 사용되는 모든 추가 바이트를 측정하는 것은 실제로 어렵습니다.
많은 수의 ConcurrentHashMap을 만드는 것이 의미가 없으므로 제한된 수의 코어 만 가질 수 있습니다. 소수의 CHM 오버 헤드는 1 센트 미만의 메모리가 될 가능성이 있습니다. –
@ PeterLawrey 나는 당신의 요점을 정말로 얻지 못합니다. "많은 양의 ConcurrentHashMap을 만드는 것은 쓸모가 없습니다." 그들은 여전히 오버 헤드가 있습니다. 게다가, 동시에 많은 CHM을 갖는 것이 이상 할지라도, 짧은 생명체가 그들의 구성에서 동시 해쉬 맵을 생성한다고 쉽게 상상할 수 있습니다. (DB 지향형 소프트웨어에서 조인 연산자를 생각해 봅시다). – Maxime
동시 수집을 사용할 수있는 이유는 컬렉션보다 코어 수가 많기 때문입니다. 코어보다 많은 콜렉션이있는 경우, 동시 액세스 권한은 거의 없습니다. –