在db40(.net)中使用大型集合

时间:2010-07-11 12:40:24

标签: c# .net db4o

我想使用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;
}

有人可以提供有关如何在这种情况下提高性能的建议吗?

2 个答案:

答案 0 :(得分:2)

我认为在这种情况下有一些选项可以改善性能。

我还发现,在这种情况下,反射开销可能会变得非常重要。因此,您可以针对您的情况尝试fast-reflector。请注意,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个存储对象之后提交。当然,您需要检查它是否真的对您的方案产生了影响。

答案 1 :(得分: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);