我正在尝试处理与 .NET DataTable 以及表中的各个 DataRows 相关的内存开销量。
换句话说,数据表占用的内存比简单地存储每列数据的正确类型数组所需的内存多多少?
我想会有一些基本的表格开销,加上每列的一些数量,然后每行再增加一些。
那么任何人都可以对这三种开销中的每一种/任何一种进行估计(并且,我猜是解释!)?
我正在尝试处理与 .NET DataTable 以及表中的各个 DataRows 相关的内存开销量。
换句话说,数据表占用的内存比简单地存储每列数据的正确类型数组所需的内存多多少?
我想会有一些基本的表格开销,加上每列的一些数量,然后每行再增加一些。
那么任何人都可以对这三种开销中的每一种/任何一种进行估计(并且,我猜是解释!)?
好吧,别忘了a DataTable
store 2?3? 数据的版本——原始版本和更新版本(可能是另一个版本?)。它也有很多参考,因为它是基于单元格的,并且对任何值类型都进行了装箱。很难量化确切的记忆......
就个人而言,我很少使用DataTable
- 在我看来,类型化的 POCO 类是一个更明智的选择。不过,我不会(直接)使用数组 -List<T>
或BindingList<T>
类似的东西会更常见。
作为粗略的衡量标准,您可以创建很多表等并查看内存使用情况;例如,下面显示了一个 ~4.3 的因素 - 即 4 倍以上的成本,但显然这在很大程度上取决于列数、行数和表数等:
// takes **roughly** 112Mb (taskman)
List<DataTable> tables = new List<DataTable>();
for (int j = 0; j < 5000; j++)
{
DataTable table = new DataTable("foo");
for (int i = 0; i < 10; i++)
{
table.Columns.Add("Col " + i, i % 2 == 0 ? typeof(int)
: typeof(string));
}
for (int i = 0; i < 100; i++)
{
table.Rows.Add(i, "a", i, "b", i, "c", i, "d", i, "e");
}
tables.Add(table);
}
Console.WriteLine("done");
Console.ReadLine();
对比
// takes **roughly** 26Mb (taskman)
List<List<Foo>> lists = new List<List<Foo>>(5000);
for (int j = 0; j < 5000; j++)
{
List<Foo> list = new List<Foo>(100);
for (int i = 0; i < 100; i++)
{
Foo foo = new Foo { Prop1 = "a", Prop3 = "b",
Prop5 = "c", Prop7 = "d", Prop9 = "e"};
foo.Prop0 = foo.Prop2 = foo.Prop4 = foo.Prop6 = foo.Prop8 = i;
list.Add(foo);
}
lists.Add(list);
}
Console.WriteLine("done");
Console.ReadLine();
(基于)
class Foo
{
public int Prop0 { get; set; }
public string Prop1 { get; set; }
public int Prop2 { get; set; }
public string Prop3 { get; set; }
public int Prop4 { get; set; }
public string Prop5 { get; set; }
public int Prop6 { get; set; }
public string Prop7 { get; set; }
public int Prop8 { get; set; }
public string Prop9 { get; set; }
}
如果您不在列上定义索引,则开销非常低。如果您使用字符串缓存,您可以获得相当低的内存占用:使用 HashSet 或 Dictionary 仅使用每个字符串值的 1 个字符串实例。这听起来很奇怪,但是如果您从数据库中获取数据,并且您有多个具有相同字符串值的行(例如“ALFKI”),则字符串值相等,但字符串实例不相等:字符串多次存储在记忆。如果您首先使用 HashSet 过滤掉重复的实例,那么您可以有效地将相同的字符串实例用于数据表中任何地方的 1 个字符串值。这可以大大减少内存占用。当然,如果字符串值已经在某处静态定义(因此不从外部源读取),则不值得努力。
这取决于您存储的数据量和数据类型。显然,数据越多,内存就越多。有一些与数据表相关的开销,这使得它有点贵。您还需要了解大对象堆。如果您存储的对象超过 85 kb,则该对象将存储在 LOH 中。这可能会对您的垃圾收集造成严重破坏,因为它需要完整的收集。如果您准备对其进行测试,请查看内存分析器以查看数据表的内存占用情况。