Sequence Layout

SequenceLayout represents the layout of arrays. To create a SequenceLayout, call MemoryLayout.sequenceLayout(numberOfElements, MemoryLayout). There is no get method or any direct way to get the nth element of an array. Instead, create a special VarHandle to the needed data within the member, then call get on that with the index. For instance, to get the x-coordinates of the structs in an array, use:

SequenceLayout arrayOfStruct = MemoryLayout.sequenceLayout(10,
    MemoryLayout.structLayout(
        ValueLayout.JAVA_INT.withName(“x”),
        ValueLayout.JAVA_INT.withName(“y”)
    ).withName(“struct”)
);
VarHandle varHandle =
arrayOfStruct.arrayElementVarHandle(PathElement.groupElement(“x”));
for (int i=0; i<10; i++) {
    System.out.println(varHandle.get(memorySegment, 
        0L,
        (long)i)
    );
}

SequenceLayout provides some interesting methods. sequenceLayout.elementCount() will, as the name suggests, give the length of the array, which is useful for passing around slices as it is not necessary to store the length itself. sequenceLayout.reshape(long dim1, long dim2, …) and sequenceLayout.flatten() are both related to reinterpreting multidimensional arrays. Multidimensional arrays are just arrays of arrays, but their layout means they can safely be reinterpreted as a single dimension array of size (dim 1 size)*(dim 2 size)*..., which is exactly what sequenceLayout.flatten() does. sequenceLayout.reshape does the inverse of sequenceLayout.flatten(), but is also fallible. Obviously, if an attempt is made to reshape an array to AxBxC but the array’s length isn’t divisible by A and B and C, this method will throw an exception. Another nice property of sequenceLayout.reshape() is that one argument may be set to -1, in which case sequenceLayout.reshape() will do the math based on the array’s length to determine what that dimension must be.

A Java type can be used to act as a wrapper around Rust slices, so SequenceLayout would feature heavily in that kind of implementation. While a slice object, composed of a pointer and a length, is not application binary interface (ABI) stable, the underlying array is ABI stable. Rust provides methods to get the pointer and length from a slice, as well as functions to construct slices from a pointer and a length, so while it is not ABI safe, it is easy enough to disassemble and reassemble into safe forms as needed. While it is easier to just keep an opaque blob of data and ask Rust any time it must be used, it is much faster for Java to have direct access to the array.

The Just-In-Time (JIT) compiler knows how array accesses work, and can optimize the corresponding Java code, possibly with automatic vectorization which is a great boost to throughput. In contrast, every time a call is made out to a Rust function, the JIT compiler has no idea what that function is doing. This means that it can not optimize the memory accesses, and it must also assume that the function breaks every optimization assumption it has. For instance, the function could touch any value in memory, preventing the JIT compiler from reordering any reads or writes from before the function call to after the function call, and vise versa.

The Rust compiler has the same issue: it does not know what the Java code is doing, so there is no way it can optimize around that such as automatic vectorization either. This does not matter so much for one-off functions, functions that are only called a few thousand times, or large functions where execution time is dominated by actually running the function and not on function call overhead, but for simple code in loops this can be brutal. And how are arrays typically used? Usually small bits of code run many times in a loop. The performance gains are too great to ignore. While doing the loop in Rust will beat Java almost every time, it is not reasonable for every possible loop body to be put in Rust. However, developers have the option to write all of their loops in Rust if they so choose. Still, SequenceLayout provides a great opportunity to allow easy, direct access to arrays and array elements for Java.

For more information on SequenceLayout, visit Oracle's official documentation.