简体   繁体   English

在循环中执行array.length或list.count是否代价高昂

[英]Is it costly to do array.length or list.count in a loop

I know that in JavaScript, creating a for loop like this: for(int i = 0; i < arr.length; i++) is costly as it computes the array length each time. 我知道在JavaScript中,创建一个这样的for循环: for(int i = 0; i < arr.length; i++)是昂贵的,因为它每次都计算数组长度。 Is this behavior costly in c# for lists and arrays as well. 对于列表和数组,这种行为在c#中是否代价高昂。 Or at compile-time is it optimized? 或者在编译时它是否经过优化? Also what about other languages such as Java, how is this handled? 还有其他语言如Java,这是如何处理的?

It is not costly in C#. 它在C#中并不昂贵。 For one thing, there is no “calculation“: querying the length is basically an elementary operation thanks to inlining. 一方面,没有“计算”:由于内联,查询长度基本上是一个基本操作。 And secondly, because ( according to its developers ), the compiler recognizes this pattern of access and will in fact optimize any (redundant) boundary checks for access on array elements. 其次,因为( 根据其开发人员 ),编译器识别这种访问模式,并且实际上将优化任何(冗余)边界检查以访问数组元素。

And by the way, I believe that something similar is true for modern JavaScript virtual machines, and if it isn't already, it will be very soon since this is a trivial optimization. 顺便说一句,我相信类似的东西对于现代JavaScript虚拟机来说也是如此,如果还没有,那么很快就会发生这种情况,因为这是一个微不足道的优化。

  1. All .Net arrays have a field containing the length of the array, so the length is not computed at usage but at creation time. 所有.Net数组都有一个包含数组长度的字段,因此在使用时但在创建时不会计算长度。

  2. The .Net virtual machine is very good at eliminating bounds checks whenever possible, this is one of those cases, where the bounds check is moved outside the loop (in most situations, and if not it's just 2 instructions overhead). .Net虚拟机非常擅长在可能的情况下消除边界检查,这是其中一种情况,其中边界检查被移动到循环之外(在大多数情况下,如果不是,它只是2个指令开销)。

Edit: 编辑:

Array Bounds Check Elimination 阵列边界检查消除

In almost any language, the answer will be "it depends". 几乎在任何语言中,答案都是“它取决于”。

Mostly, it depends on whether the compiler is clever enough to be able to tell whether the length of the list or array might change whilst you're in the loop. 大多数情况下,它取决于编译器是否足够聪明,能够判断在循环中列表或数组的长度是否可能发生变化。

That's unlikely to be defined by the language specification, though. 但是,这不太可能由语言规范定义。

So, it's probably safe to assume that the compile may not be able to figure that out. 因此,可以安全地假设编译可能无法解决这个问题。 If you really truly believe that the length of the object won't change, feel free to calculate the length first and use that in your loop control constructs. 如果你真的相信对象的长度不会改变,可以先计算长度并在循环控制结构中使用它。

But beware of other threads... 但要小心其他线程......

If it's anything like Java, it should be an O(1) operation. 如果它像Java一样,它应该是O(1)操作。

I found the following link helpful: http://www.devguru.com/Technologies/Ecmascript/Quickref/array.html 我发现以下链接很有用: http//www.devguru.com/Technologies/Ecmascript/Quickref/array.html

它还取决于该getter是进行计算还是访问已知值。

我相信如果你使用Linq Count()扩展方法,那么它可以在每次调用它时计算。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM