Mil*_*ian 19 .net c# arrays performance
在处理大型文本文件时,我遇到了以下(意外)性能下降,我无法解释.我对这个问题的目标是:
int[],但MyComplexType[]MyComplexType 是一个类,而不是结构MyComplexType包含一些string属性考虑以下C#程序:
namespace Test
{
public static class Program
{
// Simple data structure
private sealed class Item
{
public Item(int i)
{
this.Name = "Hello " + i;
//this.Name = "Hello";
//this.Name = null;
}
public readonly string Name;
}
// Test program
public static void Main()
{
const int length = 1000000;
var items = new Item[length];
// Create one million items but don't assign to array
var w = System.Diagnostics.Stopwatch.StartNew();
for (var i = 0; i < length; i++)
{
var item = new Item(i);
if (!string.IsNullOrEmpty(item.Name)) // reference the item and its Name property
{
items[i] = null; // do not remember the item
}
}
System.Console.Error.WriteLine("Without assignment: " + w.Elapsed);
// Create one million items and assign to array
w.Restart();
for (var i = 0; i < length; i++)
{
var item = new Item(i);
if (!string.IsNullOrEmpty(item.Name)) // reference the item and its Name property
{
items[i] = item; // remember the item
}
}
System.Console.Error.WriteLine(" With assignment: " + w.Elapsed);
}
}
}
Run Code Online (Sandbox Code Playgroud)
它包含两个几乎相同的循环.每个循环创建一百万个Item类实例.第一个循环使用创建的项目,然后抛弃引用(不将其保留在items数组中).第二个循环使用创建的项目,然后将引用存储在items数组中.数组项目分配是循环之间的唯一区别.
当我Release在我的机器上运行构建(优化打开)时,我得到以下结果:
Without assignment: 00:00:00.2193348
With assignment: 00:00:00.8819170
Run Code Online (Sandbox Code Playgroud)
具有数组赋值的循环明显慢于没有赋值的循环(慢4倍).
如果我更改Item构造函数以将常量字符串赋值给Nameproperty:
public Item(int i)
{
//this.Name = "Hello " + i;
this.Name = "Hello";
//this.Name = null;
}
Run Code Online (Sandbox Code Playgroud)
我得到以下结果:
Without assignment: 00:00:00.0228067
With assignment: 00:00:00.0718317
Run Code Online (Sandbox Code Playgroud)
分配的循环仍然比没有分配的循环慢约3倍
最后,如果我分配null给该Name属性:
public Item(int i)
{
//this.Name = "Hello " + i;
//this.Name = "Hello";
this.Name = null;
}
Run Code Online (Sandbox Code Playgroud)
我得到以下结果:
Without assignment: 00:00:00.0146696
With assignment: 00:00:00.0105369
Run Code Online (Sandbox Code Playgroud)
一旦没有分配字符串,没有赋值的版本最终会稍微慢一点(我假设因为所有这些实例都被释放用于垃圾回收)
为什么数组项目分配会使测试程序变得如此之慢?
是否有一个属性/语言构造/等会加速分配?
PS:我尝试使用dotTrace调查减速,但它没有结果.我看到的一件事是循环中的字符串复制和垃圾收集开销要多于没有赋值的循环(即使我预期相反).
Ree*_*sey 26
我怀疑大多数时序问题都与内存分配有关.
将项目分配到数组时,它们永远不会符合垃圾回收的条件.当您将字符串作为不是常量(实习)或null的属性时,这将导致您的内存分配要求上升.
在第一种情况下,我怀疑正在发生的事情是你正在快速地浏览对象,所以它们保留在Gen0中,并且可以快速GC,并且可以重用该内存段.这意味着您永远不必从操作系统分配更多内存.
在第二种情况下,您在对象中创建字符串,这两个字符串都是两个分配,然后存储这些字符串,因此它们不符合GC的条件.在某些时候,你需要获得更多的内存,所以你将获得分配的内存.
至于你的最后检查 - 当你设置Name为时null,if (!string.IsNullOrEmpty(item.Name))检查将阻止它被添加.因此,两个代码路径以及因此时序变得(有效地)相同,尽管第一个稍微慢一点(很可能是由于JIT第一次运行).
| 归档时间: |
|
| 查看次数: |
1434 次 |
| 最近记录: |