Câu hỏi là (bây giờ) về việc lưu trữ nhiều dữ liệu, có thể được biểu diễn bằng các kiểu nguyên thủy như int
trong Bản đồ. Một số câu trả lời ở đây rất sai lệch theo ý kiến của tôi. Hãy xem tại sao.
Tôi đã sửa đổi điểm chuẩn từ trove để đo cả thời gian chạy và mức tiêu thụ bộ nhớ. Tôi cũng đã thêm PCJ vào điểm chuẩn này, đây là một thư viện bộ sưu tập khác cho các kiểu nguyên thủy (tôi sử dụng rộng rãi loại đó). Điểm chuẩn của 'chính thức' không so sánh IntIntMaps với Java Collection Map<Integer, Integer>
, có lẽ việc lưu trữ Integers
và lưu trữ ints
không giống nhau theo quan điểm kỹ thuật. Nhưng một người dùng có thể không quan tâm đến chi tiết kỹ thuật này, anh ta muốn lưu trữ dữ liệu có thể biểu diễn một ints
cách hiệu quả.
Đầu tiên là phần có liên quan của mã:
new Operation() {
private long usedMem() {
System.gc();
return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
}
// trove
public void ours() {
long mem = usedMem();
TIntIntHashMap ours = new TIntIntHashMap(SET_SIZE);
for ( int i = dataset.size(); i-- > 0; ) {
ours.put(i, i);
}
mem = usedMem() - mem;
System.err.println("trove " + mem + " bytes");
ours.clear();
}
public void pcj() {
long mem = usedMem();
IntKeyIntMap map = new IntKeyIntOpenHashMap(SET_SIZE);
for ( int i = dataset.size(); i-- > 0; ) {
map.put(i, i);
}
mem = usedMem() - mem;
System.err.println("pcj " + mem + " bytes");
map.clear();
}
// java collections
public void theirs() {
long mem = usedMem();
Map<Integer, Integer> map = new HashMap<Integer, Integer>(SET_SIZE);
for ( int i = dataset.size(); i-- > 0; ) {
map.put(i, i);
}
mem = usedMem() - mem;
System.err.println("java " + mem + " bytes");
map.clear();
}
Tôi giả sử dữ liệu là nguyên thủy ints
, có vẻ lành mạnh. Nhưng điều này hàm ý một hình phạt thời gian chạy cho java sử dụng, vì tính năng tự động đấm bốc, không cần thiết cho các khung bộ sưu tập nguyên thủy.
Các kết quả thời gian chạy (tất nhiên không có gc()
cuộc gọi) trên WinXP, jdk1.6.0_10:
100000 đặt hoạt động 100000 chứa hoạt động
bộ sưu tập java 1938 ms 203 ms
trove 234 ms 125 ms
pcj 516 ms 94 ms
Trong khi điều này có vẻ đã quyết liệt, đây không phải là lý do để sử dụng một khung như vậy.
Lý do là hiệu suất bộ nhớ. Kết quả cho một Bản đồ chứa 100000 int
mục:
bộ sưu tập java dao động trong khoảng từ 6644536 đến 7168840 byte
trove 1853296 byte
pcj 1866112 byte
Bộ sưu tập Java cần bộ nhớ nhiều hơn ba lần so với các bộ sưu tập nguyên thủy. Tức là bạn có thể giữ dữ liệu nhiều gấp ba lần trong bộ nhớ mà không cần dùng đến IO đĩa làm giảm hiệu suất thời gian chạy theo cường độ. Và vấn đề này. Đọc highscalability để tìm hiểu lý do tại sao.
Theo kinh nghiệm của tôi, tiêu thụ bộ nhớ cao là vấn đề hiệu năng lớn nhất với Java, tất nhiên cũng dẫn đến hiệu năng thời gian chạy kém hơn. Khung bộ sưu tập nguyên thủy thực sự có thể giúp đỡ ở đây.
Vì vậy: Không, java.util không phải là câu trả lời. Và "thêm chức năng" vào các bộ sưu tập Java không phải là vấn đề khi hỏi về hiệu quả. Ngoài ra, các bộ sưu tập JDK hiện đại không "thực hiện ngay cả các bộ sưu tập Trove chuyên dụng".
Tuyên bố từ chối trách nhiệm: Điểm chuẩn ở đây còn lâu mới hoàn thành, cũng không hoàn hảo. Nó có nghĩa là để lái xe về nhà điểm, mà tôi đã trải nghiệm trong nhiều dự án. Các bộ sưu tập nguyên thủy đủ hữu ích để dung nạp API cá - nếu bạn làm việc với nhiều dữ liệu.