我的Bitset的大小是多少?

day*_*mer 8 java memory bits memory-management data-structures

我希望以System.currentTimeInMillis最小的空间存储在内存中.因为我必须将数百万存储在内存中.

我转换它给binaryString了我41 bits

这是我的计划

public class BitSetSize {
    public static void main(final String[] args) {
        final long currentTimeMillis = System.currentTimeMillis();
        final String currentTimeToBinaryString = Long.toBinaryString(currentTimeMillis);
        System.out.println("Size in bits: " + currentTimeToBinaryString.length());

        final BitSet bitSet = BitSet.valueOf(new long[]{currentTimeMillis});
        System.out.println("Bitset length: " + bitSet.length());
        System.out.println("Bitset size: " + bitSet.size());

        System.out.println("Size of biset object(bytes): " + MemoryMeasurer.measureBytes(bitSet));
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,当我运行它时,我得到了

Size in bits: 41
Bitset length: 41
Bitset size: 64
Size of biset object(bytes): 48
Run Code Online (Sandbox Code Playgroud)


-为什么bitSet.length()bitSet.size()不同?我认为length()是正确的?
- 我正在使用记忆测量器来了解bitSet它的大小,但它告诉我48 bytes,为什么不(41/8) byte呢?

我很迷惑

Ren*_*ink 5

为什么 bitSet.length() 和 bitSet.size() 不同?我假设 length() 是正确的吗?

BitSet.size()是,它使用存储比特值的内部数据结构的大小。由于BitSet内部使用long[]数组,因此大小始终是 64 位的倍数。例如,如果您在 a 中设置第 64 位,BitSetBitSet必须增加long[]数组的容量才能存储该值,因为每个 long 只能“存储”64 位。例如

BitSet bitSet = new BitSet();
for (int i = 0; i <= 64; i++) {
  bitSet.set(i, true);
  System.out.println(bitSet.size());
}
Run Code Online (Sandbox Code Playgroud)

BitSet.length()返回 中实际占用的位BitSet。所以如果你创建一个新的BitSet它的长度是 0。如果你然后设置第 4 位长度将是 5。size将保持 64,因为只需要一个长度来存储 5 位。

BitSet bitSet = new BitSet();
System.out.println(bitSet.length()); // 0
bitSet.set(4, true);
System.out.println(bitSet.size());  // 64
System.out.println(bitSet.length()); // 5
Run Code Online (Sandbox Code Playgroud)

我正在使用 memory-measurer 来了解 bitSet 的大小,但它告诉我 48 字节,为什么不是 (41/8) 字节?

因为内存填充。也称为数据结构对齐。该BitSet对象需要内存中的数学 41 字节。

  • 8 个字节用于对象头
  • 20 个字节用于 long[]
  • long数组中的8 个字节
  • wordsInUse int变量的4 个字节
  • 1 个字节用于 sizeIsSticky boolean

但是 jvm 无法分配 41 位,因此它将其四舍五入为 8 的下一个倍数。即 48。

此大小可能会有所不同,因为对象标头大小可能因一种 JVM 实现而异。所以如果对象头是 16 个字节。总数将为 49,jvm 将其四舍五入为 8 的下一个倍数。在本例中为 56。


Iva*_*tov 4

首先,我想建议使用正确的工具来分析 JVM 中的对象布局方案 - JOL。在您的情况下( java -jar jol-cli/target/jol-cli.jar internals java.util.BitSet) JOL 会产生以下结果:

Running 64-bit HotSpot VM.
Using compressed references with 3-bit shift.
Objects are 8 bytes aligned.
Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]

java.util.BitSet object internals:
 OFFSET  SIZE    TYPE DESCRIPTION                    VALUE
      0     4         (object header)                01 00 00 00 (00000001 00000000 00000000 00000000) (1)
      4     4         (object header)                00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4         (object header)                f4 df 9f e0 (11110100 11011111 10011111 11100000) (-526393356)
     12     4     int BitSet.wordsInUse              0
     16     1 boolean BitSet.sizeIsSticky            false
     17     3         (alignment/padding gap)        N/A
     20     4  long[] BitSet.words                   [0]
Instance size: 24 bytes (reported by Instrumentation API)
Space losses: 3 bytes internal + 0 bytes external = 3 bytes total
Run Code Online (Sandbox Code Playgroud)

由于静态字段,您的计算不正确,因此空BitSet本身保留 24 个字节。请注意,这些计算并非 100% 准确,因为它没有考虑long[]对象的大小。所以正确的结果是java -jar jol-cli/target/jol-cli.jar externals java.util.BitSet

Running 64-bit HotSpot VM.
Using compressed references with 3-bit shift.
Objects are 8 bytes aligned.
Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]

java.util.BitSet@6b25f76bd object externals:
          ADDRESS       SIZE TYPE             PATH                           VALUE
        7ae321a48         24 java.util.BitSet                                (object)
        7ae321a60         24 [J               .words                         [0]
Run Code Online (Sandbox Code Playgroud)

这意味着空BitSet本身使用 48 个字节,包括长数组。您还可以获取不同VM模式下的估计对象布局java -jar jol-cli/target/jol-cli.jar estimates java.util.BitSet