回答额外的问题:
我已经实现了一个 SizeReader+Writer。我需要 DataAccess 还是 SizedWriter 对于原始数组来说足够快?我查看了 ByteArrayDataAccess,但由于内部 HeapBytesStore 对 byte[]/ByteBuffers 如此特殊,尚不清楚如何将其移植到长数组中?
使用 ofDataAccess
而不是SizedWriter
允许在Map.put(key, value)
. 但是,如果在您的用例putOneValue()
中(如上面的示例)是主要的查询类型,则不会有太大区别。如果Map.put(key, value)
(和replace()
等,即任何“全值写入”操作)很重要,仍然可以实现DataAccess
for LongList
。它看起来像这样:
class LongListDataAccess implements DataAccess<LongList>, Data<LongList>,
StatefulCopyable<LongListDataAccess> {
transient ByteStore cachedBytes;
transient boolean cachedBytesInitialized;
transient LongList list;
@Override public Data<LongList> getData(LongList list) {
this.list = list;
this.cachedBytesInitialized = false;
return this;
}
@Override public long size() {
return ((long) list.size()) * Long.BYTES;
}
@Override public void writeTo(RandomDataOutput target, long targetOffset) {
for (int i = 0; i < list.size(); i++) {
target.writeLong(targetOffset + ((long) i) * Long.BYTES), list.get(i));
}
}
...
}
为了提高效率,方法size()
和方法writeTo()
是关键。但是正确实现所有其他方法(我没有在这里写)也很重要。仔细阅读DataAccess
,Data
和javadocs,也非常注意教程中的Understanding,和Custom serialization checklist。StatefulCopyable
StatefulCopyable
DataAccess
SizedReader
读/写锁定是在同一台机器上的多个进程读取和写入之间进行调解还是在单个进程中进行调解?
跨进程是安全的,请注意该接口称为InterProcess ReadWriteUpdateLock。
存储对象时,事先不知道可变大小,因为值会导致堆和持久文件中的碎片?
为键存储一次值,之后不更改值的大小(而不是删除键)不会导致外部碎片。更改值的大小或删除键可能会导致外部碎片。ChronicleMapBuilder.actualChunkSize()
配置允许在外部和内部碎片之间进行交易。chunk 越大,外部碎片越少,但内部碎片越多。如果您的值明显大于页面大小(4 KB),您可以设置大到荒谬的块大小,并且仍然具有受页面大小限制的内部碎片,因为 Chronicle Map 能够利用 Linux 中的惰性页面分配功能。