在GC .NET中结构胜过类的结构的真实示例

时间:2018-11-14 10:28:30

标签: c# struct garbage-collection

我致力于介绍.NET中的GC最佳实践。 我创建了一些示例来说明对性能的影响,例如LargeObject轮询,消除世代之间的引用,正确的GC模式等做法。 但是,当我尝试创建显示结构与类优势的示例时,我失败了。使用class \ struct的每段代码都以相同的方式工作(我使用“%time in GC”计数器)。我可以根据内存消耗情况来创建示例,但是看起来GC可以处理它们,并且GC中的%time没有差别。 有人可以提供示例吗?

以下是一些示例:

while (true)
        {
            var collection = 
                Enumerable.Range(0, 100000000)
                .Select(x => new ModelStruct(x))
                .ToList();//Change to Model but no significant difference
            var result = collection.Average(x=>x.Id);
        }


while (true){
            Parallel.ForEach(Enumerable.Range(0, 8), y =>
            {
                var collection = Enumerable.Range(0, 100000000)
                .Select(x => new Model(x))
                .ToList();//Change to Model but no significant difference
                var result = collection.Average(x => x.Id);
            });
        }

var tasks = Enumerable.Range(0, size).Select(x =>
            Task.Run(() =>
            {
                var model = new Model(x);
                return model;
            })
        ).ToArray();
var result = (await Task.WhenAll(tasks)).Average(x => x.HashCode);

模型是class \ struct,具有10多个Guid作为属性

2 个答案:

答案 0 :(得分:0)

尝试以多种方式存储整数:

  1. 将它们放入int[]List<int>中。这是结构版本,将使用4*N个字节的内存。
  2. 将它们装箱放在object[]List<object>中。这是类版本(使用框作为一种简单的方法,但是您也可以使用class { int x; }。这将在x64上使用8*N+16*N+4*N字节的内存。这是用于对象引用和对象标头的和整数值。

尝试遍历该列表并将其求和,然后尝试在循环中反复调用GC.Collect()。使用较大的N,以使差异真正重要。

您会发现内存使用量,GC时间和处理列表内容的时间存在很大差异。

结构并不总是更快,但您要求提供一个示例以突出其可能的优点。

答案 1 :(得分:0)

创建一个相对较大的struct / class(10个以上value-type字段),创建一个大数组,然后在方法的帮助下处理该数组。当该项传递给该方法时,它将使编译器将整个结构复制到调用堆栈中,但是对于类,则仅复制指针。 另外,如果数组/列表是项和null(或空结构)的混合,则您的内存消耗肯定会有所不同。