What is the size of my bicep?

I want to keep System.currentTimeInMillis in memory with the least possible space. because I have to keep millions of them in my memory.

I converted it to binaryString which gave me 41 bits

Here is my program

 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)); } } 

But when I run it, I get

 Size in bits: 41 Bitset length: 41 Bitset size: 64 Size of biset object(bytes): 48 

Question
- What is the difference bitSet.length() and bitSet.size() ? I assume length() correct?
- I use a memory meter to find out the size of the bitSet , but he told me 48 bytes , why is it not (41/8) byte ?

I'm confused

+7
java memory-management memory data-structures bits
source share
5 answers

First of all, I want to recommend the right tool for analyzing object layout schemes in JVMs - JOL . In your case ( java -jar jol-cli/target/jol-cli.jar internals java.util.BitSet ) JOL gives the following result:

 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 

Your calculations were not correct due to static fields, so an empty BitSet itself reserves 24 bytes. Please note that these calculations are not 100% accurate because the size of the long[] object was not taken into account. So, the correct results are 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] 

This means that an empty BitSet itself uses 48 bytes, including a long array. You can also get an approximate layout of the object in different modes of VM java -jar jol-cli/target/jol-cli.jar estimates java.util.BitSet

+4
source share

Your current code cannot be the repository for millions of long ( System.currentTimeInMillis ). You can use troove TLongHashSet, or you should look at sparse bitset . But BitSet has an int index, so you have to compress long from currentTimeInMillis to int. For example. bitSetIndex = (int) (currentTimeInMillis - initialTime). This gives you an interval of 2 ^ 32 milliseconds (~ 50 days), starting with initialTime.

 //store sample for bitset: bitSet.set(System.currentTimeInMillis()); 

EDIT

One BitSet object allocates more than 100 bytes on the heap. Therefore, you must reuse a single BitSet for a large number of long values. The easiest way is to use the long value as an index inside the BitSet and set the value to true in that index. But there are several problems (I described them above):

  • Bitset has an int index not long
  • java.util.BitSet is not memory efficient.
+2
source share

See java doc BitSet .

Each bit has a current size, which is the number of bits of space the bit is currently in use. Note that size is related to the implementation of the bit set, so it may change with the implementation. bit set length refers to the logical length of the bit set and is determined independently of the implementation.

+1
source share

Why are the values ​​of bitSet.length () and bitSet.size () different? I assume the length () is correct?

BitSet.size() is the size of the internal data structure that it uses to store bit values. Because BitSet internally uses the long[] array, the size is always a multiple of 64 bits. For example. if you set the 64th bit to BitSet , BitSet must increase the capacity of the long[] array to preserve this value, because each long can only β€œstore” 64 bits. For example.

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

BitSet.length() returns the actual occupied bits in a BitSet . Therefore, if you create a new BitSet , the length is 0. If you then set the 4th bit, the length will be 5. size will remain 64, since only 5 long bits are required to store 5 bits.

 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 

I use a memory meter to find out about the bitSet size, but it will tell me 48 bytes, why is it not (41/8) bytes?

Due to full memory. Also called data structure alignment . A BitSet object requires a mathematical 41 bytes in memory.

  • 8 bytes for the object header
  • 20 bytes for long[]
  • 8 bytes for long in an array
  • 4 bytes for the variable wordsInUse int
  • 1 byte for sizeIsSticky boolean

But jvm cannot allocate 41 bits, so it rounds it to the next multiple of 8. This is 48.

This size may vary because the size of the object's header may vary from one JVM implementation to another. Therefore, if the object header is 16 bytes. The total will be 49, and jvm will round it to the next multiple of 8. In this case, 56.

+1
source share

As mentioned by BetaRide, the actual size that BitSet uses is implementation specific. However, in Oracle / OpenJDK implementations (at least 6, 7, and 8), the main element of the state is long[] words . This means that the size is always a multiple of 64.

As for 48 bytes, I calculate in code:

  • 16 bytes for the BitSet object itself
  • 20 bytes for the object long[] (16 for the object, 4 for the length)
  • 8 bytes for the contents of the array (each element has 8 bytes, but you only have one)
  • 4 bytes for int wordsInUse
  • 1 byte for boolean sizeIsSticky

What gives 49 is just around the corner that you see. If these object headers are compressed , but an addition is also added, then probably from where 48 comes from.

0
source share

All Articles