[…] access to a dynamic array can be faster than a static array!
我已经知道动态数组位于堆上(它们是用引用/指针实现的).
到目前为止,我知道动态数组的访问时间更长.但这与分配是一回事吗?就像我调用SetLength(MyDynArray,5)比创建XXX的MyArray =数组[0..4]要慢吗?
So far I know that the access time is better on dynamic arrays.
这是不正确的.该文中的陈述完全是错误的.
But is that the same thing with the allocation? Like if I called
SetLength(MyDynArray, 5)
is that slower than creating aMyArray = array[0..4] of XXX
?
一个常见的谬论是静态数组在堆上分配.它们可以是全局变量,因此在加载模块时会自动分配.它们可以是局部变量并在堆栈上分配.可以通过调用New或GetMem动态分配它们.或者它们可以包含在复合类型(例如记录或类)中,因此以任何方式分配拥有对象.
说清楚之后,让我们考虑一些常见的情况.
局部变量,静态数组类型
如前所述,声明为局部变量的静态数组在堆栈上分配.分配是自动的,基本上是免费的.将分配视为由编译器执行(当它生成用于保留堆栈帧的代码时).因此,分配没有运行时成本.可能存在访问运行时成本,因为这可能会生成页面错误.这一切都完全正常,如果你想使用一个小的固定大小的数组作为局部变量,那么就没有更快的方法.
类的成员变量,静态数组类型
同样,如上所述,分配由包含对象执行.静态数组是为对象保留的空间的一部分,当实例化对象时,在堆上分配了足够的内存.堆分配的成本通常不会很大程度上取决于要分配的块的大小.该语句的一个例外可能是非常大的块,但我假设你的数组大小相当小,数十或数百个字节.有了这些知识,我们可以再次看到,分配成本基本上为零,因为我们已经为包含对象分配了内存.
局部变量,动态数组类型
动态数组由指针表示.所以你的局部变量是在堆栈上分配的指针.相同的参数适用于任何其他局部变量,例如上面讨论的静态数组类型的局部变量.分配基本上是免费的.在您对此变量执行任何操作之前,您需要通过调用SetLength来分配它.这导致堆分配,这是昂贵的.同样,当你完成后,你必须解除分配.
类的成员变量,动态数组类型
同样,动态数组指针的分配是免费的,但您必须调用SetLength进行分配.这是一个堆分配.当对象被销毁时,也需要重新分配.
结论
对于在编译时已知长度的小数组,使用静态数组可以实现更高效的分配和释放.
请注意,我只考虑在此分配.如果分配是使用对象所花费时间的相对不重要的部分,那么这种性能特征可能无关紧要.例如,假设在程序启动时分配数组,然后在程序的持续时间内重复使用.在这种情况下,访问时间主导分配时间,并且分配时间之间的差异变得无关紧要.
另一方面,想象一下在程序生命周期中反复调用的一个简短函数,让我们假设这个函数是性能瓶颈.如果它在小型阵列上运行,那么使用动态阵列的分配成本可能很大.
你很少能用性能来制定严格的规则.您需要了解这些工具的工作原理,并了解您的程序如何使用这些工具.然后,您可以形成关于哪种编码策略可能表现最佳的意见,然后您应该通过分析来测试这些意见.您会比您预期的直觉不是表现的良好预测因素更容易感到惊讶.