คำถามคือ (ตอนนี้) เกี่ยวกับการจัดเก็บข้อมูลจำนวนมากซึ่งสามารถแสดงโดยใช้ประเภทดั้งเดิมเช่นint
ในแผนที่ บางคำตอบที่นี่ทำให้เข้าใจผิดในความคิดของฉัน มาดูกันว่าทำไม
ฉันแก้ไขเกณฑ์มาตรฐานจากtroveเพื่อวัดการใช้งานจริงและหน่วยความจำ ฉันยังเพิ่มPCJไปยังเกณฑ์มาตรฐานนี้ซึ่งเป็นอีกหนึ่งคอลเลกชันห้องสมุดสำหรับประเภทดั้งเดิม (ฉันใช้ที่หนึ่งอย่างกว้างขวาง) เกณฑ์มาตรฐาน 'ทางการ' ไม่ได้เปรียบเทียบ IntIntMaps กับ Java Collection ของการMap<Integer, Integer>
เก็บIntegers
และการจัดเก็บints
อาจไม่เหมือนกันจากมุมมองทางเทคนิค แต่ผู้ใช้อาจไม่ใส่ใจกับรายละเอียดทางเทคนิคนี้เขาต้องการจัดเก็บข้อมูลที่แสดงได้ints
อย่างมีประสิทธิภาพ
ก่อนอื่นส่วนที่เกี่ยวข้องของรหัส:
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();
}
ฉันถือว่าข้อมูลมาในรูปแบบดั้งเดิมints
ซึ่งดูเหมือนว่ามีเหตุผล แต่สิ่งนี้แสดงถึงการลงโทษแบบรันไทม์สำหรับ java util เนื่องจาก auto-Boxing ซึ่งไม่จำเป็นสำหรับกรอบการรวบรวมแบบดั้งเดิม
ผลลัพธ์รันไทม์ (โดยไม่ต้องgc()
เรียกใช้) บน WinXP, jdk1.6.0_10:
การดำเนินงานที่ใส่ได้ 100,000 การดำเนินการที่มีอยู่ 100,000 ครั้ง
คอลเลกชัน java 1938 ms 203 ms
trove 234 ms 125 ms
pcj 516 ms 94 ms
แม้ว่าสิ่งนี้อาจดูรุนแรง แต่นี่ไม่ใช่เหตุผลที่จะใช้เฟรมเวิร์กดังกล่าว
เหตุผลก็คือประสิทธิภาพของหน่วยความจำ ผลลัพธ์ของแผนที่ที่มีint
ข้อมูล100,000 รายการ:
คอลเลกชัน java จะแกว่งระหว่าง 6644536 ถึง 7168840 ไบต์
trove 1853296 ไบต์
pcj 1866112 ไบต์
Java Collections ต้องการหน่วยความจำมากกว่าสามเท่าเมื่อเทียบกับเฟรมเวิร์กการรวบรวมดั้งเดิม เช่นคุณสามารถเก็บข้อมูลได้มากถึงสามเท่าในหน่วยความจำโดยไม่ต้องหันไปใช้ดิสก์ IO ซึ่งลดประสิทธิภาพการทำงานของรันไทม์ลงตามขนาด และเรื่องนี้ อ่านคะแนนสูงเพื่อหาสาเหตุ
จากประสบการณ์ของฉันการใช้หน่วยความจำสูงเป็นปัญหาด้านประสิทธิภาพที่ใหญ่ที่สุดของ Java ซึ่งแน่นอนว่าส่งผลให้ประสิทธิภาพการทำงานของ runtime แย่ลงด้วยเช่นกัน กรอบการรวบรวมดั้งเดิมสามารถช่วยได้ที่นี่จริงๆ
ดังนั้น: ไม่ java.util ไม่ใช่คำตอบ และ "การเพิ่มฟังก์ชั่นการใช้งาน" ลงในคอลเล็กชัน Java ไม่ใช่ประเด็นเมื่อถามเกี่ยวกับประสิทธิภาพ นอกจากนี้คอลเล็กชั่น JDK ที่ทันสมัยก็ไม่ได้ "ทำผลงานได้ดีแม้แต่คอลเล็กชั่น Trove พิเศษ"
ข้อจำกัดความรับผิดชอบ: มาตรฐานที่นี่อยู่ไกลจากความสมบูรณ์และไม่สมบูรณ์แบบ มันมีความหมายที่จะขับรถกลับบ้านจุดที่ฉันมีประสบการณ์ในหลายโครงการ การรวบรวมดั้งเดิมมีประโยชน์เพียงพอที่จะทนต่อ API คาว - หากคุณทำงานกับข้อมูลจำนวนมาก