我最近改变了
this.FieldValues = new object[2, fieldValues.GetUpperBound(1) + 1];
for (int i = 0; i < FieldCount; i++)
{
this.FieldValues[Current, i] = fieldValues[Current, i];
this.FieldValues[Original, i] = fieldValues[Original, i];
}
Run Code Online (Sandbox Code Playgroud)
至
FieldValues = new object[2, fieldValues.GetLength(1)];
Array.Copy(fieldValues, FieldValues, FieldValues.Length);
Run Code Online (Sandbox Code Playgroud)
其中Current和Original的值分别为常数0和1.FieldValues是一个字段,fieldValues是一个参数.
在我使用它的地方,我发现Array.Copy()版本更快.但另一位开发人员表示,他在一个独立的程序中对Array.Copy()进行for循环计时,并发现for循环更快.
Array.Copy()可能不是真的更快吗?我认为它应该是超级优化的!
根据我自己的经验,我发现在性能方面我无法相信自己的直觉.因此,我保留了一个快速而肮脏的基准测试应用程序(我称之为"StupidPerformanceTricks"),我用它来测试这些场景.这是非常宝贵的,因为我已经对性能技巧做了各种令人惊讶和反直觉的发现.同样重要的是要记住在发布模式下运行基准测试应用程序,而不附加调试器,否则您将无法获得JIT优化,并且这些优化可能会产生显着差异:技术A在调试模式下可能比技术B慢,但在发布模式下显着更快,优化的代码.
也就是说,一般来说,我自己的测试经验表明,如果你的数组是<~32个元素,你可以通过滚动自己的复制循环来获得更好的性能 - 可能是因为你没有方法调用开销,这可能很重要.但是,如果循环大于~32个元素,则使用Array.Copy()可以获得更好的性能.(如果你要复制整数或浮点数或类似的东西,你可能还想调查Buffer.BlockCopy(),它比小数组的Array.Copy()快10%.)
但所有这一切,真正的答案是,"编写自己的测试,尽可能接近这些精确的替代品,用循环包装它们,给循环足够的迭代,让它至少咀嚼2-3秒CPU,然后自己比较备选方案."
.Net 在幕后工作的方式,我猜在优化的情况下,Array.Copy 会避免边界检查。
如果您对任何类型的集合执行循环,默认情况下 CLR 将检查以确保您没有传递集合的结尾,然后 JIT 要么必须进行运行时评估,要么发出不通过的代码需要检查。(查看我评论中的文章以获得更详细的信息)
您可以修改此行为,但通常不会节省那么多。除非你在一个严格执行的内循环中,每毫秒都很重要,那就是。
如果 Array 很大,我会使用 Array.Copy,如果它很小,两者都应该执行相同的操作。
我确实认为边界检查会为您创造不同的结果。
| 归档时间: |
|
| 查看次数: |
5632 次 |
| 最近记录: |