2012-06-19 25 views
10

Có ai biết chi phí bộ nhớ của ConcurrentHashMap (so với HashMap "cổ điển") không?ConcurrentHashMap memory overhead

  • Khi xây dựng?
  • Khi chèn phần tử?
+0

Việc tạo một số lượng lớn ConcurrentHashMap không có nghĩa là bạn chỉ có một số lõi giới hạn. Chi phí của một số lượng nhỏ CHM có thể là ít hơn 1 cent giá trị của bộ nhớ. –

+0

@PeterLawrey Tôi thực sự không hiểu điểm của bạn. "Thật vô dụng khi tạo ra một lượng lớn ConcurrentHashMap", vậy thì sao? Họ vẫn có một chi phí. Bên cạnh đó, ngay cả khi rõ ràng là có nhiều CHM cùng một lúc, người ta có thể dễ dàng tưởng tượng rằng các đối tượng sống ngắn tạo ra một bản đồ băm đồng thời khi xây dựng (giả sử một toán tử nối trong một phần mềm định hướng DB?). – Maxime

+0

Lý do bạn có thể sử dụng các bộ sưu tập đồng thời là vì bạn có nhiều lõi hơn các bộ sưu tập. Nếu bạn có nhiều bộ sưu tập hơn lõi, rất khó bạn sẽ có quyền truy cập đồng thời. –

Trả lời

6

Nếu bạn chạy như sau với -XX:-UseTLAB -XX:NewSize=900m -mx1g trên JVM 64 bit.

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(); 
} 

bạn nhận được với Java 6 và 7 cho một triệu mục nhập.

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. 

Tám MB bộ nhớ mất khoảng 5 xu.

+0

Độ tin cậy của việc sử dụng bộ nhớ là đáng tin cậy như thế nào? – assylias

+0

Bạn có thể giải thích điểm sử dụng phân bổ cục bộ luồng không? Cảm ơn! – assylias

+0

Có thể khác với Java 5 hoặc các JVM khác so với HotSpot hoặc OpenJDK nhưng tôi sẽ ngạc nhiên nếu nó khác biệt đáng kể. Sự khác biệt có thể nhỏ hơn trên các JVM 32 bit. –

2

Tôi thực sự không hiểu tiền đề của câu hỏi - bạn cần đồng thời hay không.

Tuy nhiên, theo this link, dấu chân bộ nhớ của trống ConcurrentHashMap là 1700 byte. Nó khuyến cáo rằng bạn sử dụng ConcurrentHashMap nếu bạn có nhiều chủ đề cần truy cập đọc/ghi, nhưng một Hashtable nếu bạn có nhiều chủ đề cần truy cập đọc nhưng một với ghi.

+0

Liên kết quá cũ để có liên quan. Thật vậy, bài viết này đã được xuất bản (04/28/2012) trước khi Java 7 và việc thực hiện có thể đã thay đổi. Hơn nữa, câu trả lời của bạn là không đầy đủ kể từ khi tôi yêu cầu chèn quá (là có một). – Maxime

+2

@Maxime Triển khai có thể không thay đổi nhiều, nhưng trong bất kỳ trường hợp nào, nó mô tả phương pháp họ đã sử dụng để tìm dữ liệu. Một chút nghiên cứu cho thấy rằng không ai khác đã thực hiện nó. – purtip31

4

ConcurrentHashMap không sử dụng bộ nhớ nhiều hơn đáng kể so với HashMap, cả lúc xây dựng và lúc chèn.

Tại intialization

ConcurrentHashMap sử dụng gần như cùng một lượng bộ nhớ như một HashMap, có thể hơi hơn cho vài biến và khóa sổ kế toán thêm.

Trong khi khởi tạo, ConcurrentHashMap tạo 16 Phân đoạn để lưu trữ khóa-giá trị, mỗi Phân đoạn tương đương với HashMap.

Dung lượng/kích thước của mỗi Phân đoạn là 1/16 tổng dung lượng ban đầu. Vì vậy, về bản chất, ConcurrentHashMap tạo 16 HashMaps nhỏ tương đương với một HashMap. Mỗi phân đoạn có khóa riêng và một vài biến giữ sách (đếm, ngưỡng, vv), đây là chi phí bổ sung bộ nhớ.

Bạn có thể kiểm soát số lượng Phân đoạn được tạo bởi ConcurrentHashMap bằng cách chuyển giá trị thích hợp cho concurrencyLevel tham số ConcurrentHashMap. Nhỏ hơn giá trị này, sau đó không gian ít hơn sẽ được sử dụng nhưng tranh cãi nhiều hơn khi số lượng cao các chủ đề cập nhật Bản đồ. Cao hơn giá trị này, sau đó nhiều Phân đoạn sẽ được tạo nhưng hiệu suất của các bản cập nhật song song sẽ nhanh hơn. Lưu ý: Giá trị cao hơn đáng kể cho thông số concurrencyLevel, ảnh hưởng đến cả không gian và thời gian.

Chi phí nhỏ này trong bộ nhớ là những gì nhà phát triển sẵn sàng chấp nhận để đổi lấy đồng thời.

Tại Insertion

Khi phân đoạn được điền, kích thước của phân khúc đó sẽ được tăng lên. Chính sách để tăng kích thước cũng giống như HashMap. thông số loadfactor quyết định thời điểm tăng kích thước của Phân đoạn. Chỉ lưu ý rằng Phân đoạn được lấp đầy sẽ được tăng lên.Một lần nữa, bộ nhớ trên không giống như HashMap.

Nhìn chung, ConcurrentHashMap không sử dụng bộ nhớ đáng kể nhiều hơn HashMap, nhưng thật khó để đo từng byte phụ được sử dụng bởi ConcurrentHashMap.