Search code examples
javaarraysmemory-managementchronicle

How is @Array(length= ?) Annotation in OpenHFT/Chronicle-Values Used


This question is regarding Chronicle-Values

One example found in the site is:

interface SomeStats {
    @Array(length=100)
    long getPercentFreqAt(int index);
    void setPercentFreqAt(int index, long percentFreq);
    long addPercentFreqAt(int index, long addition);
}

Here the annotation is only applied to the one of the methods. Does this imply all methods afterwards are treated as working on the array data?

In one of the test cases I found

package net.openhft.chronicle.values;

public interface HasArraysInterface {
    @Array(length = 4)
    void setFlagAt(int idx, boolean flag);

    boolean getFlagAt(int idx);

    @Array(length = 4)
    void setByteAt(int idx, byte b);

    byte getByteAt(int idx);

    @Array(length = 4)
    void setShortAt(int idx, short s);

    short getShortAt(int idx);

    @Array(length = 4)
    void setCharAt(int idx, char ch);

    char getCharAt(int idx);

    @Array(length = 4)
    void setIntAt(int idx, int i);

    int getIntAt(int idx);

    @Array(length = 4)
    void setFloatAt(int idx, float f);

    float getFloatAt(int idx);

    @Array(length = 4)
    void setLongAt(int idx, long l);

    long getLongAt(int idx);

    @Array(length = 4)
    void setDoubleAt(int idx, double d);

    double getDoubleAt(int idx);

    @Array(length = 4)
    void setStringAt(int idx, @MaxUtf8Length(8) String s);

    String getStringAt(int idx);
}

What I understood from this is that you can have multiple arrays within this interface where @Array(length = 4) applies to methods ending with At until the next annotation. Is this right?

In addition can you have something like the following to simulate an array of 4 double and array of 8 strings:

    @Array(length = 4)
    void setDoubleAt(int idx, double d);

    double getDoubleAt(int idx);

    @Array(length = 8)
    void setStringAt(int idx, @MaxUtf8Length(8) String s);

    String getStringAt(int idx);

What is the memory layout of multiple arrays allocated with multiple @Array(length= ?) within one interface? Can you choose between column oriented or row oriented layout? How will the layouts be handled if the length is different?

Also instead of:

interface SomeStats {
    @Array(length=100)
    long getPercentFreqAt(int index);
    void setPercentFreqAt(int index, long percentFreq);
    long addPercentFreqAt(int index, long addition);
}

can you write it as:

@Array(length=100)
interface SomeStats {
    long getPercentFreqAt(int index);
    void setPercentFreqAt(int index, long percentFreq);
    long addPercentFreqAt(int index, long addition);
}

implying @Array(length=100) applies to the whole interface.

Also can you defer specifying the length until the point of creation?


Solution

    1. Here the annotation is only applied to the one of the methods. Does this imply all methods afterwards are treated as working on the array data?

    From @Array javadoc:

    This annotation must be put on a single method accessing the array elements: getter, or setter, or adder, etc.

    I. e. @Array should be put on one (any) method, accessing a field. "Field" is defined by standard accessor methods, and name, i. e. in your example, in the SomeStats value interface, there is a single (array) field, named PercentFreq. If you add method like getAnotherField(), setAnotherField() to this interface, it would be a separate field, to which @Array annotation doesn't apply, i. e. it would be a "scalar" field, unless you put @Array on getAnotherField() or setAnotherField() and add int index parameters to those methods, and -At suffix.

    2.

    What I understood from this is that you can have multiple arrays within this interface where @Array(length = 4) applies to methods ending with At until the next annotation. Is this right?

    No, not "until the next annotation". Annotation is applied to a field. Field accessor methods (identified by the field name) could go in any order in the interface definition.

    3.

    What is the memory layout of multiple arrays allocated with multiple @Array(length= ?) within one interface? Can you choose between column oriented or row oriented layout? How will the layouts be handled if the length is different?

    In your example, layout would be:

    Double element 0 (8 bytes)
    Double element 1 (8 bytes)
    Double element 2 (8 bytes)
    Double element 3 (8 bytes)
    String element 0 (9 bytes: 1 bytes to encode size + 8 bytes of reserved space)
    ...
    String element 7 (9 bytes)
    

    To have row-based alignment, your should define another interface:

    interface Row {
        void setDouble(double d);
        double getDouble();
    
        void setString(@MaxUtf8Length(8) String s);
        String getString();
    }
    

    And then define array or rows:

    interface MyTopInterface {
        @Array(length=8)
        void setRowAt(int index, Row row);
        Row getRowAt(int index);
    }
    

    This will be equally efficient and take the same amount of memory, as "column orientied" layout. Read about nested structures in the tutorial.

    4.

    implying @Array(length=100) applies to the whole interface.

    You cannot do this, use the pattern suggested above (nested interface)

    5.

    Also can you defer specifying the length until the point of creation?

    No, the whole idea of Chronicle Values is that their size total is statically known.