par*_*007 7 language-agnostic performance
在性能方面,最好是"直接"多次访问数组元素,还是将其值赋给变量并使用该变量?假设我将在以下代码中多次引用该值.
这个问题背后的原因是,访问数组元素可能每次完成时都需要一些计算成本,而不需要额外的空间.另一方面,将值存储在变量中会消除此访问成本,但会占用额外的空间.
// use a variable to store the value
Temp = ArrayOfValues(0)
If Temp > 100 Or Temp < 50 Then
Dim Blah = Temp
...
// reference the array element 'directly'
If ArrayOfValues(0) > 100 Or ArrayOfValues(0) < 50 Then
Dim Blah = ArrayOfValues(0)
...
Run Code Online (Sandbox Code Playgroud)
我知道这是一个微不足道的例子,但假设我们在谈论实际使用中的更大规模(其中值将被多次引用),在什么时候需要考虑空间和计算时间之间的权衡(如果有的话)?
这是标记语言不可知论,但我真的不相信它是。这篇文章回答了这个问题的 C 和 C++ 版本。
优化编译器可以处理“裸”数组访问;在 C 或 C++ 中,如果中间没有调用任何函数,则没有理由认为编译器不会记住内存位置的值。例如
int a = myarray[19];
int b = myarray[19] * 5;
int c = myarray[19] / 2;
int d = myarray[19] + 3;
Run Code Online (Sandbox Code Playgroud)
但是,如果 myarray 不仅定义为 int[],而且实际上是某种“奇特”的东西,尤其是某些用户定义的容器类型以及operator[]()在另一个翻译单元中定义的函数,那么每次请求该值时都必须调用该函数(因为函数返回内存中某个位置的数据,而本地函数不知道该函数的结果是常量)。
即使使用“裸”数组,如果您围绕函数调用多次访问相同的内容,编译器同样必须假设该值已更改(即使它可以记住地址本身)。例如
int a = myarray[19];
NiftyFunction();
int b = myarray[19] * 8;
Run Code Online (Sandbox Code Playgroud)
编译器无法知道 myarray[19] 在函数调用前后具有相同的值。
所以-一般来说,如果您知道一个值在局部范围内是常量,请将其“缓存”在局部变量中。您可以进行防御性编程并使用断言来验证您对事物的这种情况:
int a = myarray[19];
NiftyFunction();
assert(myarray[19] == a);
int b = a * 8;
Run Code Online (Sandbox Code Playgroud)
最后一个好处是,如果它们没有埋在某个数组中,那么在调试器中检查值会容易得多。
内存消耗的开销非常有限,因为对于引用类型来说,它只是一个指针(几个字节),并且大多数值类型也只需要几个字节。
在大多数语言中,数组是非常有效的结构。获取索引不涉及任何查找,而只涉及一些数学运算(每个数组槽占用 4 个字节,因此第 11 个槽位于偏移量 40 处)。那么边界检查可能会产生一些开销。为新的本地变量分配内存并释放它也需要一些 CPU 周期。因此,最终还取决于通过复制到本地变量来消除多少数组查找。
事实是,你确实需要非常糟糕的硬件,或者有非常大的循环,这才变得非常重要,并且如果对其进行了适当的测试。我个人经常选择单独的变量,因为我发现它使代码更具可读性。
顺便说一句,你的例子很奇怪,因为你在创建本地变量之前进行了 2 次数组查找:) 这更有意义(消除了 2 次以上的查找)
Dim blah = ArrayOfValues(0)
if blah > 100 or blah < 50 then
...
Run Code Online (Sandbox Code Playgroud)