如何使用Chronicle Map在随机索引上使用get/set来序列化/反序列化long []值?

jun*_*kie 5 java low-latency chronicle chronicle-map off-heap

我是编年史的新手.我正在尝试使用chronicle-map对离堆映射进行建模,其中键是原始short,值是原始长数组.对于给定的映射,长数组值的最大大小是已知的.但是我将有多个这种类型的映射,每个映射对于长数组值可能具有不同的最大大小.我的问题涉及密钥和值的序列化/反序列化.

从阅读文档我明白,对于密钥,我可以使用值类型ShortValue并重用该接口的实现实例.关于值,我找到了关于DataAccess和SizedReader的页面,它给出了byte []的一个例子,但我不确定如何将它改编为long [].我有一个额外的要求是我需要在长数组中的任意索引处获取和设置值,而无需每次都支付整个值的完整序列化/反序列化的成本.

所以我的问题是:如何构建地图时我如何建模值类型?如果每个地图知道最大尺寸并且我需要能够随机读写,那么我需要为long []数组设置什么序列化/反序列化代码每次没有序列化/反序列化整个值有效负载的索引?理想情况下,long []将直接编译/解码到堆外,而不会在堆上中间转换为byte [],并且chronicle-map代码也不会在运行时分配.谢谢.

lev*_*tov 3

首先,我建议使用某种LongList接口抽象来代替long[],它将更容易处理大小可变性,提供替代的享元实现等。

如果您只想读取/写入大型列表中的单个元素,您应该使用高级上下文 API

/** This method is entirely garbage-free, deserialization-free, and thread-safe. */
void putOneValue(ChronicleMap<ShortValue, LongList> map, ShortValue key, int index,
        long element) {
    if (index < 0) throw throw new IndexOutOfBoundsException(...);
    try (ExternalMapQueryContext<ShortValue, LongList, ?> c = map.getContext(key)) {
        c.writeLock().lock(); // (1)
        MapEntry<ShortValue, LongList> entry = c.entry();
        if (entry != null) {
            Data<LongList> value = entry.value();
            BytesStore valueBytes = (BytesStore) value.bytes(); // (2)
            long valueBytesOffset = value.offset();
            long valueBytesSize = value.size();
            int valueListSize = (int) (valueBytesSize / Long.BYTES); // (3)
            if (index >= valueListSize) throw new IndexOutOfBoundsException(...);
            valueBytes.writeLong(valueBytesOffset + ((long) index) * Long.BYTES,
                element);
            ((ChecksumEntry) entry).updateChecksum(); // (4)
        } else {
            // there is no entry for the given key
            throw ...
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

笔记:

  1. 必须writeLock()从头开始获取,否则调用方法时会自动获取readLock() context.entry(),之后就无法将读锁升级为写锁。请仔细阅读HashQueryContextjavadoc
  2. Data.bytes()正式返回RandomDataInput,但您可以确定(它在 javadoc 中指定)它实际上是(即和的组合)Data.bytes()的实例。BytesStoreRandomDataInputRandomDataOutput
  3. 假设提供了正确的SizedReaderSizedWriter(或)。请注意,使用了“字节/元素联合大小”技术,文档部分DataAccess中给出的示例相同。您可以基于该示例类。SizedReaderSizedWriterPointListSizeMarshallerLongListMarshaller
  4. 此转换是指定的,请参阅ChecksumEntryjavadoc以及文档中有关校验和的部分。如果您有一个纯粹在内存中(未持久化)的历史记录图,或者关闭了校验和,则可以省略此调用。

单元素读取的实现类似。