在内存中表示大数据

时间:2012-09-13 07:01:51

标签: c#

目前,我正在开发一个项目,我需要将数据的GB数据传输到客户端计算机上来执行某项任务,并且任务需要整个数据,因为它会对数据进行一些分析,并有助于决策制定过程。

所以问题是,在不影响客户端计算机和应用程序性能的情况下,将大量数据管理到内存中的最佳实践和合适方法是什么。

注意:在加载应用程序时,我们可以花时间将数据从数据库传输到客户机,这在我们的案例中是完全可以接受的。但是一旦数据在启动时加载到应用程序中,性能就非常重要。

1 个答案:

答案 0 :(得分:14)

如果没有问题陈述,这有点难以回答,即您目前面临的问题,但以下只是一些想法,基于我们在类似场景中的一些近期经验。然而,要改变这种类型的模型需要付出很多努力 - 所以它还取决于您可以投入多少资金来“修复”它,而且我不能保证“您的问题”与“我们的问题”相同问题“,如果你明白我的意思。所以,如果以下方法对您不起作用,请不要交叉!


将大量数据加载到内存中总会产生一些影响,但是,我想我知道你在做什么......

当天真地加载那么多数据时,你将拥有许多(数百万?)个对象和相似或更多数量的引用。你显然想要使用x64,所以引用会加起来 - 但就性能来说,最大的问题是垃圾收集。你有很多永远无法收集的对象,但GC会知道你正在使用大量的内存,并且会定期尝试 。这是我查看in more detail here的内容,但下图显示了影响 - 特别是那些“峰值”都是GC杀戮性能:

http://marcgravell.blogspot.co.uk/2011/10/assault-by-gc.html

对于这种情况(加载了大量数据,从未发布过),我们使用结构切换到,即将数据加载到:

struct Foo {
    private readonly int id;
    private readonly double value;
    public Foo(int id, double value) {
        this.id = id;
        this.value = value;
    }
    public int Id {get{return id;}}
    public double Value {get{return value;}}
}

并直接将存储在数组(不是列表)中:

Foo[] foos = ...

这意味着因为其中一些结构非常大,我们不希望它们在堆栈上复制很多次,但是你可以使用数组:

private void SomeMethod(ref Foo foo) {
     if(foo.Value == ...) {blah blah blah}
}
// call ^^^
int index = 17;
SomeMethod(ref foos[index]);

请注意,我们已直接传递对象 - 它从未被复制过; foo.Value实际上直接在内部数组中查找。当您需要对象之间的关系时,棘手的位开始。您无法在此处存储引用,因为它是struct,您无法存储。但是,你可以做的是存储索引(进入数组)。例如:

struct Customer {
      ... more not shown
      public int FooIndex { get { return fooIndex; } }
}

不如customer.Foo那么方便,但以下效果很好:

Foo foo = foos[customer.FooIndex];
// or, when passing to a method, SomeMethod(ref foos[customer.FooIndex]);

关键点:

  • 我们现在使用“引用”的一半大小(int是4个字节; x64上的引用是8个字节)
  • 我们内存中没有数百万个对象标题
  • 我们没有一个巨大的对象图供GC查看;只有少数几个GC可以快速查看令人难以置信的
  • 但使​​用起来不太方便,加载时需要一些初始处理

补充说明:

  • 字符串是杀手;如果你有数百万字符串,那就有问题;至少,如果你有重复的字符串,请确保你做一些自定义实习(不是string.Intern,这将是坏的),以确保你只有一个实例的每个重复值,而不是800,000字符串与相同的内容
  • 如果你有重复的有限长度数据,而不是子列表/数组,你可能会考虑fixed数组;这需要unsafe代码,但避免使用其他无数的对象和引用

作为一个额外的脚注,有了这么多的数据,你应该非常认真地考虑你的序列化协议,即你如何通过网络发送数据。我强烈建议远离XmlSerializerDataContractSerializerBinaryFormatter等内容。如果您想了解这个主题,请告诉我。