Space 需要在内存中保留最大的整数数组
Space required to keep largest integer array in memory
我正在审查一个算法,它保留一个整数数组,输入的大小是动态的。所以根据我的计算,它可能需要
integer MAX_VALUE * int size = ?
2^31 integers * 4 bytes = ?
2147483648 integers * 4 bytes = 8 Gigabytes
这个计算正确吗? JVM 会使用如此连续的 space 来存储 int 数组还是需要考虑其他事项?
数组大小最大值 < Integer.MAX_VALUE
不,您的最大值不正确。
Java 中数组元素数量的限制比 Integer.MAX_VALUE
(2,147,483,647), depending on the version of Java, the host OS, and how Java was compiled. See by Ivan Mamontov on the Question, 少一点。
是的,最大数组 int
≈ 8 gigs
因此 int
的最大数组的大小将大致为 ( Integer.MAX_VALUE - 8L ) * 32L
位,即 68,719,476,448 位,即 8,589,934,556 个八位字节。
是的,大约 8 GB 内存。请记住:这是数组的 连续 内存。所以:
- JVM 和宿主 OS 可能需要做大量工作才能生成这样的数组,具体取决于运行时那一刻内存的碎片化程度。
- 如果主机硬件没有足够的实际内存,您将陷入虚拟内存,由此产生的分页可能会导致糟糕的性能。
如果您真的在工作中突破这些限制,请务必进行实际测试。您可能需要考虑为超大内存设计的 Java 替代实现,例如 Azul Systems 的 Zing。
数组的理论大小为:
numberOfElementsInTheArray * 4 字节
12 个字节的 headers(int[]
是一个 Object)。实际上 headers 的大小取决于你使用的标志和 on the JVM version you are running this
4个字节来保留数组的length
填充。
例如:(我准备使用JOL for this):
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 个整数 * 4 个字节)
- 12 为 headers
- 长度为 4
- 0 用于填充
如果将此数组更改为 Integer
,情况将发生巨大变化。 Integer
是一个 Object,因此您将在数组中存储一个引用(可以是 4
或 8
字节,具体取决于 UseCompressedOops
标志),加上每个Integer
个实例需要 2 个 headers(每个 Integer
是一个 Object)。
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 个字节 headers
- 数组长度为 4 个字节
- 0 字节填充
该数组的每个引用都指向一个 Integer
,每个 Object 都将具有 16 bytes
:
- 内部
int
的 4 个字节
- 12 字节 headers
- 0 字节填充
我正在审查一个算法,它保留一个整数数组,输入的大小是动态的。所以根据我的计算,它可能需要
integer MAX_VALUE * int size = ?
2^31 integers * 4 bytes = ?
2147483648 integers * 4 bytes = 8 Gigabytes
这个计算正确吗? JVM 会使用如此连续的 space 来存储 int 数组还是需要考虑其他事项?
数组大小最大值 < Integer.MAX_VALUE
不,您的最大值不正确。
Java 中数组元素数量的限制比 Integer.MAX_VALUE
(2,147,483,647), depending on the version of Java, the host OS, and how Java was compiled. See
是的,最大数组 int
≈ 8 gigs
因此 int
的最大数组的大小将大致为 ( Integer.MAX_VALUE - 8L ) * 32L
位,即 68,719,476,448 位,即 8,589,934,556 个八位字节。
是的,大约 8 GB 内存。请记住:这是数组的 连续 内存。所以:
- JVM 和宿主 OS 可能需要做大量工作才能生成这样的数组,具体取决于运行时那一刻内存的碎片化程度。
- 如果主机硬件没有足够的实际内存,您将陷入虚拟内存,由此产生的分页可能会导致糟糕的性能。
如果您真的在工作中突破这些限制,请务必进行实际测试。您可能需要考虑为超大内存设计的 Java 替代实现,例如 Azul Systems 的 Zing。
数组的理论大小为:
numberOfElementsInTheArray * 4 字节
12 个字节的 headers(
int[]
是一个 Object)。实际上 headers 的大小取决于你使用的标志和 on the JVM version you are running this4个字节来保留数组的
length
填充。
例如:(我准备使用JOL for this):
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 个整数 * 4 个字节)
- 12 为 headers
- 长度为 4
- 0 用于填充
如果将此数组更改为 Integer
,情况将发生巨大变化。 Integer
是一个 Object,因此您将在数组中存储一个引用(可以是 4
或 8
字节,具体取决于 UseCompressedOops
标志),加上每个Integer
个实例需要 2 个 headers(每个 Integer
是一个 Object)。
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 个字节 headers
- 数组长度为 4 个字节
- 0 字节填充
该数组的每个引用都指向一个 Integer
,每个 Object 都将具有 16 bytes
:
- 内部
int
的 4 个字节 - 12 字节 headers
- 0 字节填充