我想使用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;
}
有人可以提供有关如何在这种情况下提高性能的建议吗?
答案 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);