Search code examples
dictionarychroniclechronicle-map

Does it make sense to store byte values in Map or it will still use 4 bytes?


In Java in-memory there is no difference between byte or int - both will be represented as 4 bytes.

Does for Chronicle Map the difference exist, i.e. does Chronicle Map store byte values as 8 bits or still use 32?

Same question if byte is an object property.


Solution

  • In primitive map implementations (fastutil, koloboke, gs, hppc) byte values are implemented as a separate byte[] array, so they actually take only 1 byte. If a byte is a field of another on-heap Java object (which is a Map value), indeed, the object size is rounded up to 8-byte boundary, so a single byte field could "take" 8 bytes. But more often, it "takes" 0 bytes, because the field is placed in the already existing alignment holes.

    For Chronicle Map, a value could freely be 1 byte in size. (And even 0 bytes, this is how ChronicleSet is currently implmeneted -- a ChronicleMap with 0-byte dummy values.) This is true for all Chronicle Map versions (2, 3).


    Edit -- answer to the comment.

    If you have a constantly sized structure e. g. 6 byte fields, easiest and efficient way - to use data value generation mechanishm:

    interface MyValue {
        byte getA(); void setA(byte a);
        byte getB(); void setB(byte b);
        byte getC(); void setC(byte c);
        byte getD(); void setD(byte d);
        byte getE(); void setE(byte e);
        byte getF(); void setF(byte f);
    }
    
    map = ChronicleMapBuilder.of(Key.class, MyValue.class).entries(1000).create();
    
    // Chronicle Map 2 syntax
    MyValue value = DataValueClasses.newDirectReference(MyValue.class);
    try (Closeable handle = map.getUsingLocked(key, value)) {
        // access the value here
        System.out.println(value);
    }
    
    // Chronicle Map 3 syntax
    try (ExternalMapQueryContext<Key, MyValue, ?> q = map.queryContext(key)) {
        // if not sure the key is present in the map, check q.entry() != null
        MyValue value = q.entry().value().get();
        // access the value here
        System.out.println(value);
    }
    

    It will take exactly 6 bytes per value.