3

我想使用 db4o 作为自定义缓存实现的后端。通常,我的程序涉及将大约 40,000,000 个对象加载到内存中并同时处理它们。显然这需要大量内存,我想也许将一些对象(不在缓存中的对象)持久化到 db4o 数据库中。我的初步测试表明 db4o 比我想要的要慢一些(大约 1,000,000 个对象需要 17 分钟才能保持)。但是,我使用的是最基本的设置。

我正在做这样的事情:

using (var reader = new FileUnitReader(Settings, Dictionary, m_fileNameResolver, ObjectFactory.Resolve<DataValueConverter>(), ObjectFactory.Resolve<UnitFactory>()))
using (var db = Db4oEmbedded.OpenFile(Db4oEmbedded.NewConfiguration(), path))
{
    var timer = new Stopwatch();
    timer.Start();
    IUnit unit = reader.GetNextUnit();
    while (unit != null)
    {
        db.Store(unit);
        unit = reader.GetNextUnit();
    }
    timer.Stop()
    db.Close();

    var elapsed = timer.Elapsed;
}

任何人都可以就如何在这种情况下提高性能提供建议吗?

4

2 回答 2

2

好吧,我认为在这种情况下有几个选项可以提高性能。

我还发现,在这种情况下,反射开销可能会占据很大一部分。因此,您可能应该为您的情况尝试快速反射器。请注意,FastReflector 会消耗更多内存。但是,在您的情况下,这并不重要。你可以像这样快速反射器:

var config = Db4oEmbedded.NewConfiguration();
config.Common.ReflectWith(new FastNetReflector());

using(var container = Db4oEmbedded.OpenFile(config, fileName))
{
}

当我进行类似的微小“基准测试”时,我发现更大的缓存大小也会稍微提高性能,即使您写入数据库也是如此:

var config = Db4oEmbedded.NewConfiguration();
config.File.Storage = new CachingStorage(new FileStorage(), 128, 1024 * 4);

其他注意事项:db4o 的事务处理并未真正针对大型事务进行优化。当您在一个事务中存储 1'000'000 个对象时,提交可能需要很长时间,或者您的内存不足。因此,您可能希望更频繁地提交。例如,在每 100'000 个存储对象之后提交。当然,您需要检查它是否真的对您的场景产生影响。

于 2010-07-11T16:27:00.900 回答
1

您可以尝试的另一个小改进:

通过将 .Ext() 添加到 OpenFile() 调用来获取扩展接口。

存储后清除每个对象。

using (var db = Db4oEmbedded.OpenFile(Db4oEmbedded.NewConfiguration(), path).Ext())
// ....
db.Store(unit);
db.Purge(unit);
// ....

这样,您将减少 db4o 在当前事务中必须维护的引用数量。

如果您使用存储配置(即 db4o 下面的可插入文件系统),您可能最有可能获得另一项重大改进。最新的 8.0 版本具有更好的缓存实现,当您使用更大的缓存时,它不会降低缓存维护的性能缓存页数。

我建议您使用 Gamlor 建议的缓存设置尝试最新的 8.0 版本,看看是否会有所不同:

config.File.Storage = new CachingStorage(new FileStorage(), 128, 1024 * 4);

如果是这样,您也可以尝试更高的数字:

config.File.Storage = new CachingStorage(new FileStorage(), 1280, 1024 * 40);
于 2010-07-12T18:22:30.193 回答