พื้นที่ที่ต้องการเพื่อเก็บอาร์เรย์จำนวนเต็มมากที่สุดในหน่วยความจำ
ฉันกำลังตรวจสอบอัลกอริทึมและเก็บอาร์เรย์ของจำนวนเต็มขนาดของอินพุตเป็นแบบไดนามิก ดังนั้นจากการคำนวณของฉันอาจใช้เวลามากถึง
integer MAX_VALUE * int size = ?
2^31 integers * 4 bytes = ?
2147483648 integers * 4 bytes = 8 Gigabytes
การคำนวณนี้ถูกต้องหรือไม่? JVM จะใช้พื้นที่ที่ต่อเนื่องกันมากขนาดนี้เพื่อจัดเก็บ int array หรือมีสิ่งอื่นที่ต้องพิจารณาหรือไม่?
คำตอบ
ขนาดตามทฤษฎีของอาร์เรย์จะเป็น:
numberOfElementsInTheArray * 4 ไบต์
ส่วนหัว 12 ไบต์ (
int[]
เป็นวัตถุ) จริงๆแล้วขนาดของส่วนหัวขึ้นอยู่กับแฟล็กที่คุณใช้และบนเวอร์ชัน JVM ที่คุณกำลังเรียกใช้4 ไบต์เพื่อเก็บ
length
อาร์เรย์การขยายความ.
ตัวอย่างเช่น: (ฉันจะใช้JOL สำหรับสิ่งนี้ ):
int [] x = new int[10];
for(int i=0;i<10;++i){
x[i] = 9999;
}
System.out.println(GraphLayout.parseInstance((Object)x).toPrintable());
จะส่งออก:
[I@7a81197dd object externals:
ADDRESS SIZE TYPE PATH VALUE
70fe45268 56 [I [9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999]
ดังนั้นจึงมี56 bytes
:
- 40 สำหรับค่าเอง (10 ints * 4 bytes)
- 12 สำหรับส่วนหัว
- 4 สำหรับความยาว
- 0 สำหรับช่องว่างภายใน
หากคุณเปลี่ยนอาร์เรย์นี้Integer
สิ่งต่างๆจะเปลี่ยนไปอย่างมาก Integer
เป็นวัตถุดังนั้นคุณจะจัดเก็บการอ้างอิงภายในอาร์เรย์ (ซึ่งอาจเป็น4
หรือ8
ไบต์ขึ้นอยู่กับUseCompressedOops
แฟล็ก) บวกกับแต่ละInteger
อินสแตนซ์จะต้องมี 2 ส่วนหัว (แต่ละส่วนInteger
คือวัตถุ)
Integer[] y = new Integer[10];
for(int i=0;i<10;++i){
y[i] = 9999;
}
System.out.println(GraphLayout.parseInstance((Object)y).toFootprint());
ซึ่งจะแสดง:
[Ljava.lang.Integer;@369f73a2d footprint:
COUNT AVG SUM DESCRIPTION
1 56 56 [Ljava.lang.Integer;
10 16 160 java.lang.Integer
11 216 (total)
ทั้งหมด216 bytes
:
- 4 ไบต์สำหรับการอ้างอิงแต่ละรายการ (ฉัน
UseCompressedOop
เปิดอยู่) รวม 40 ไบต์ - 12 ไบต์ส่วนหัวของอาร์เรย์
- ความยาว 4 ไบต์ของอาร์เรย์
- ช่องว่างภายใน 0 ไบต์
การอ้างอิงแต่ละรายการจากอาร์เรย์นั้นชี้ไปInteger
ที่อ็อบเจ็กต์แต่ละตัวจะมี16 bytes
:
- 4 ไบต์สำหรับด้านใน
int
ถือ - ส่วนหัว 12 ไบต์
- ช่องว่างภายใน 0 ไบต์
ขนาดอาร์เรย์สูงสุด < Integer.MAX_VALUE
ไม่สูงสุดของคุณไม่ถูกต้อง
ขีด จำกัด ของจำนวนองค์ประกอบในอาร์เรย์ใน Java นั้นน้อยกว่าInteger.MAX_VALUE(2,147,483,647) เล็กน้อยขึ้นอยู่กับเวอร์ชันของ Java ระบบปฏิบัติการโฮสต์และวิธีการคอมไพล์ Java ดูคำตอบนี้โดย Ivan Mamontov ในคำถามทำไมฉันไม่สามารถสร้างอาร์เรย์ที่มีขนาดใหญ่ได้ .
ใช่อาร์เรย์ที่ใหญ่ที่สุดint
≈ 8 กิ๊ก
ดังนั้นขนาดของอาร์เรย์สูงสุดint
จะเป็น( Integer.MAX_VALUE - 8L ) * 32L
บิตประมาณ68,719,476,448 บิตซึ่งเป็น 8,589,934,556 อ็อกเทต
ใช่แล้วหน่วยความจำประมาณ 8 กิ๊ก และจำไว้ว่านี่คือหน่วยความจำที่ต่อเนื่องกันสำหรับอาร์เรย์ ดังนั้น:
- อาจมีงานสำคัญในส่วนของJVMและโฮสต์ OS เพื่อสร้างอาร์เรย์ดังกล่าวขึ้นอยู่กับว่าหน่วยความจำที่แยกส่วนในขณะนั้นระหว่างรันไทม์นั้นเป็นอย่างไร
- หากฮาร์ดแวร์ของโฮสต์มีหน่วยความจำจริงไม่เพียงพอคุณจะเข้าสู่หน่วยความจำเสมือนจริงซึ่งการแบ่งหน้าผลลัพธ์อาจทำให้ประสิทธิภาพแย่ลง
ทำการทดสอบในโลกแห่งความเป็นจริงเสมอหากคุณกำลังผลักดันขีด จำกัด เหล่านี้ในงานของคุณจริงๆ และคุณอาจต้องการพิจารณาการใช้งานทางเลือกของ Java ที่ออกแบบมาสำหรับหน่วยความจำขนาดใหญ่มากเช่นZingโดย Azul Systems