Fory row format is heavily inspired by spark tungsten row format, but with changes:
The initial Fory java row data structure implementation is modified from spark unsafe row/writer.
See Encoders.bean Javadoc for a list built-in supported types.
To begin using the row format from Java, start with the Encoders class:
// Many built-in types and collections are supported
public record MyRecord(int key, String value) {}
// The encoder supplier is relatively expensive to create
// It is thread-safe and should be re-used
Supplier<RowEncoder<MyRecord>> encoderFactory =
Encoders.buildBeanCodec(MyRecord.class)
.build();
// Each individual encoder is relatively cheap to create
// It is not thread-safe, but may be reused by the same thread
var encoder = encoderFactory.get();
byte[] encoded = encoder.encode(new MyRecord(42, "Test"));
MyRecord deserialized = encoder.decode(encoded);
The default row format is cross-language compatible and alignment-padded for maximum performance. When data size is a greater concern, the compact format provides an alternate encoding that uses significantly less space.
Enable the compact codec on the encoder builder:
Supplier<RowEncoder<MyRecord>> encoderFactory =
Encoders.buildBeanCodec(MyRecord.class)
.compactEncoding()
.build();
Optimizations include:
It is possible to register custom type handling and collection factories for the row format - see Encoders.registerCustomCodec and Encoders.registerCustomCollectionFactory. For an interface, Fory can synthesize a simple value implementation, such as the UuidType below.
A short example:
public interface UuidType {
UUID f1();
UUID[] f2();
SortedSet<UUID> f3();
}
static class UuidEncoder implements CustomCodec.MemoryBufferCodec<UUID> {
@Override
public MemoryBuffer encode(final UUID value) {
final MemoryBuffer result = MemoryBuffer.newHeapBuffer(16);
result.putInt64(0, value.getMostSignificantBits());
result.putInt64(8, value.getLeastSignificantBits());
return result;
}
@Override
public UUID decode(final MemoryBuffer value) {
return new UUID(value.readInt64(), value.readInt64());
}
}
static class SortedSetOfUuidDecoder implements CustomCollectionFactory<UUID, SortedSet<UUID>> {
@Override
public SortedSet<UUID> newCollection(final int size) {
return new TreeSet<>();
}
}
Encoders.registerCustomCodec(UUID.class, new UuidEncoder());
Encoders.registerCustomCollectionFactory(
SortedSet.class, UUID.class, new SortedSetOfUuidDecoder());
RowEncoder<UuidType> encoder = Encoders.bean(UuidType.class);