我致力于介绍.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作为属性
答案 0 :(得分:0)
尝试以多种方式存储整数:
int[]
或List<int>
中。这是结构版本,将使用4*N
个字节的内存。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(或空结构)的混合,则您的内存消耗肯定会有所不同。