做出来的参数C#有任何性能影响我应该知道的?(像例外)
我的意思是,out
在循环中使用一个参数的方法是一个好主意,每秒运行几百万次?
我知道它很丑,但我使用它的方式与Int32.TryParse
使用它们相同- 返回一个bool
告诉我是否有一些验证是成功的,并且如果成功则有一个out
包含一些额外数据的参数.
我怀疑你会发现使用out
参数有任何显着的性能损失.你必须以某种方式将信息反馈给调用者 - out
这只是一种不同的方式.如果在方法中广泛使用out参数,您可能会发现存在一些损失,因为它可能意味着每次访问都需要额外的重定向级别.但是,我不认为它会很重要.正常情况下,编写最易读的代码并在尝试进一步优化之前测试性能是否已经足够好.
编辑:其余部分是有效的.它只适用于大值类型,通常应该避免使用:)
我不同意Konrad的断言,"所有类型的返回值> 32位的处理方式与机器级别的out参数相似或相同"但是.这是一个小测试应用程序:
using System; using System.Diagnostics; using System.Runtime.CompilerServices; struct BigStruct { public Guid guid1, guid2, guid3, guid4; public decimal dec1, dec2, dec3, dec4; } class Test { const int Iterations = 100000000; static void Main() { decimal total = 0m; // JIT first ReturnValue(); BigStruct tmp; OutParameter(out tmp); Stopwatch sw = Stopwatch.StartNew(); for (int i=0; i < Iterations; i++) { BigStruct bs = ReturnValue(); total += bs.dec1; } sw.Stop(); Console.WriteLine("Using return value: {0}", sw.ElapsedMilliseconds); sw = Stopwatch.StartNew(); for (int i=0; i < Iterations; i++) { BigStruct bs; OutParameter(out bs); total += bs.dec1; } Console.WriteLine("Using out parameter: {0}", sw.ElapsedMilliseconds); } [MethodImpl(MethodImplOptions.NoInlining)] public static BigStruct ReturnValue() { return new BigStruct(); } [MethodImpl(MethodImplOptions.NoInlining)] public static void OutParameter(out BigStruct x) { x = new BigStruct(); } }
结果:
Using return value: 11316 Using out parameter: 7461
基本上通过使用out参数,我们将数据直接写入最终目标,而不是将其写入small方法的堆栈帧,然后将其复制回Main方法的堆栈帧.
尽管如此批评基准应用程序 - 我可能错过了一些东西!
没有性能影响.out
从技术角度来看,与任何旧的论证基本相同.虽然复制大量数据可能听起来似乎有道理(例如对于大型结构),但这实际上与返回值相同.
事实上,所有类型> 32位的返回值的处理方式与机器级别的out
参数类似.
请注意,最后一条语句并不建议out
在.NET 中返回value == 参数.Jon的基准测试显示,这显然(并且令人遗憾)并非如此.实际上,为了使它相同,在C++编译器中使用了命名返回值优化.类似的东西可能会在JIT的未来版本中完成,以提高返回大型结构的性能(但是,由于.NET中的大型结构非常少见,这可能是一种不必要的优化).
但是,(并且由于我对x86程序集的知识非常有限),从函数调用返回对象通常需要在调用站点分配足够的空间,推送堆栈上的地址并通过将返回值复制到堆栈中来填充它.这与基本相同out
,只是省略了值的不必要的临时副本,因为可以直接访问目标内存位置.
这不是一个性能问题,而是早先出现的问题 - 你不能在C#4.0中使用它们.
就个人而言,我倾向于out
在我的私有代码中使用相当大的参数(即在一个类中,有一个方法可以返回多个值而不使用单独的类型) - 但我倾向于在公共API上避免它们,除了bool Try{Something}(out result)
模式.