在C#中有没有一种内存效率高的方法来在内存中保存200万项的集合?
集合必须是可搜索的,最好是通过LINQ查询,并且必须是快速的。
集合中的类型相当简单,没有长字符串:
public class Item
{
public string Name { get; set; }
public string Category { get; set; }
public bool IsActive { get; set; }
public DateTimeOffset CreatedAt { get; set; }
public IReadOnlyList<string> Tags { get; set; }
}
在类型之上使用简单的列表
作为类
或结构
仍然需要大约2 GB的内存。 有没有更好的办法?
你可以做这些点,然后你会看到是否有麻烦:
>
您可以启用gcAllowVeryLargeObjects以启用大于2 GB的数组。
让类实现。 当您在class和struct之间进行选择时,性能并不是主要因素。 我认为没有理由在这里使用struct。 请参见在类和结构之间进行选择。
根据您的搜索筛选器,您必须重写GetHashCode和Equal。
您需要改变属性,还是只在集合中搜索对象?
如果您只是想要研究,并且您的属性重复了很多次,那么您可以让一个属性被多个对象使用。
这样,值只存储一次,对象只存储引用。
只有当您不想改变属性时,才可以这样做。
例如,如果两个对象具有相同的类别:
public class Category
{
public string Value { get; }
public Category(string category)
{
Value = category;
}
}
public class Item
{
public string Name { get; set; }
public Category Category { get; set; }
public bool IsActive { get; set; }
public DateTimeOffset CreatedAt { get; set; }
public IReadOnlyList<string> Tags { get; set; }
}
class Program
{
public void Init()
{
Category category = new Category("categoryX");
var obj1 = new Item
{
Category = category
};
var obj2 = new Item
{
Category = category
};
}
}
如果您运行的是64位,我预计2M对象不会出现任何主要的内存问题。 列表的最大大小限制为2GB,但引用只有8个字节,因此列表应该在这个限制之下。 总内存使用量主要取决于字符串的大小。 还会有一些对象开销,但如果需要存储多个字符串,这是很难避免的。
还有,如何测量记忆力? 。NET运行时可能会过度分配内存,因此对象的实际内存使用率可能大大低于Windows报告的内存。 使用内存探查器获得精确计数。
如果字符串在多个对象之间重复,那么如果您能够使用相同的实例来删除它们的重复,则可能会有一个很大的胜利。
使用struct而不是类可以避免一些开销,所以我做了一些测试:
确切的时间将取决于您正在进行的查询,这些数字主要用于比较。
结论是,带有常规for循环的常规对象列表可能是最快的。 而且,迭代所有对象的速度相当快,因此在大多数情况下,它应该不会导致重大的性能问题。
如果需要更好的性能,则需要创建某种索引,这样就可以避免对所有项进行迭代。 如果不知道您正在执行哪种查询,就很难知道这方面的确切策略。
一种选择可以是使用内存数据库的某种变体,这可以提供大多数索引功能。 SQLite就是一个例子