提问者:小点点

C#:>200万对象内存效率


在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的内存。 有没有更好的办法?


共2个答案

匿名用户

你可以做这些点,然后你会看到是否有麻烦:

>

  • 您可以启用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而不是类可以避免一些开销,所以我做了一些测试:

    • 使用LINQ-46MS的对象列表
    • 用于循环的对象列表-16ms
    • 用于循环-250ms的结构列表
    • 使用for循环的ref-return的只读结构列表:180ms

    确切的时间将取决于您正在进行的查询,这些数字主要用于比较。

    结论是,带有常规for循环的常规对象列表可能是最快的。 而且,迭代所有对象的速度相当快,因此在大多数情况下,它应该不会导致重大的性能问题。

    如果需要更好的性能,则需要创建某种索引,这样就可以避免对所有项进行迭代。 如果不知道您正在执行哪种查询,就很难知道这方面的确切策略。

    一种选择可以是使用内存数据库的某种变体,这可以提供大多数索引功能。 SQLite就是一个例子