我正在尝试使用xodus作为存储,因为我想要一个这种类型的存储,并且基准测试表明它很快。
然而,在实践中,写入似乎真的很慢。
我正在建立两个商店,模式如下:
environment = Environments.newInstance(xodusDBFolder);
Store initialStateStore = environment.computeInTransaction(new TransactionalComputable<Store>()
{
@Override
public Store compute(@NotNull final Transaction txn)
{
return environment.openStore("initialStateStore", StoreConfig.WITHOUT_DUPLICATES, txn);
}
});然后,我使用这样的模式编写代码:
environment.executeInTransaction((Transaction txn) -> {
ArrayByteIterable key = IntegerBinding.intToEntry(c.getNid());
ByteIterable oldValue = store.get(txn, key);
ArrayByteIterable value;
if (oldValue != null)
{
//merge contents...
}
....
value = new ArrayByteIterable(rawData);
store.put(txn, key, value);
});将数据输入到这个模式中,我有两个线程,每个线程读取和解析我正在填充的每个环境的数据。
我已经期望我的读取/解析到瓶颈...但在实践中,瓶颈在于xodus编写。
我认为我可以让xodus并行写入,所以我在线程池中进行写入-但这使性能变得更差。到目前为止,最好的性能似乎发生在我禁用垃圾收集器,并且只允许一个线程写入xodus存储的时候。
我做错了什么吗?对于一个线程,慢的部分是在ReadWriteTransaction.doCommit()下面发生的所有事情。对于多线程,它们都只是阻塞并等待ReentrantTransactionDispatcher.waitForPermits().
我可能会使用两个不同的环境,这可能会有1/2的帮助……但是如果我不能让两个线程同时向xodus写入无关的键,而不发生争用,那就好像出了什么问题。
顺便说一句,这里是谈论xodus用法的最佳场所吗?我没有看到论坛之类的东西。
发布于 2018-06-06 18:13:34
即使写入的数据看起来完全解耦(无关),对单个环境的并发写入也总是争用的。有两种方法可以减少争用:
executeInExclusiveTransaction方法而不是executeInTransaction来对写入进行排序。这种方法不仅可以安排用户事务,还可以安排后台GC事务。缺点是它还安排了写的准备工作(在传递给方法的lambda中定义),这可能会在parallel.exodus.log.cache.shared=false。此外,不同的环境可以物理隔离在不同的存储设备上。https://stackoverflow.com/questions/50688932
复制相似问题