2

我在一些 Rebol 代码中发现了这样的一行:

dups: make block! 10000

为什么要在 Rebol 中使用预分配?

只写有什么问题:

dups: copy []
4

4 回答 4

7

第一件事:你不会在 Rebol 中“分配一个变量”,而是“预先分配一个系列缓冲区”(它恰好被代码示例中的一个单词引用,但它可能只是位于一个块中)。

快速回答:每次您将数据插入或追加到系列时,如果系列缓冲区已满,则内存管理器会将系列重新分配给更大的缓冲区。如果您多次扩展一个系列(例如在循环中将数据附加到系列),如果您不预先分配,您最终可能会为所有重新分配消耗大量额外内存,并且可能在某个时候,也触发垃圾收集器通道。这通常会导致程序执行速度大大减慢并消耗大量额外内存。将系列缓冲区预分配到足够大的大小以容纳所有最终数据,将避免所有这些内存和性能问题。

在 的情况下dups: copy [],您正在分配一个最小系列缓冲区(大小可能为 8 或 16 个插槽),因此如果您的所有数据都不适合此缓冲区,您的程序将支付重新分配的(沉重)成本( s)。也是[]一个预先分配的最小大小的文字系列,您只是将其用作构建新系列的模板,因此最好避免浪费内存并改为编写:dups: make block! 0这将分配一个块!系列最小尺寸,不浪费额外的块!系列。

于 2013-04-16T15:42:53.060 回答
2

预分配缓冲区对于低级函数 read-io 是必不可少的

如果您需要例如在读取数据时访问确切的错误代码,您可以使用 read-io 而不是在打开的端口上复制。

read-io 与 c 语言中的 READ 相当。您为 read-io 提供了预先分配的固定缓冲区和缓冲区长度。如果您尝试使用超过预先分配的缓冲区长度的 read-io,您将自行承担风险

于 2013-06-14T12:15:42.140 回答
0

我刚测试

>> a: make block! 10000
>> b: copy []
>> delta-time [loop 10000 [append a 1]]
== 0:00:00.004315
>> delta-time [loop 10000 [append b 1]]
== 0:00:00.005795

差别只是不到百分之一秒。

然后我重新启动 rebol 并测试:

>> a: make block! 10000
>> b: copy []
>> delta-time [loop 20000 [append a "test"]]
== 0:00:00.000238
>> delta-time [loop 20000 [append b "test"]]
== 0:00:00.000223

没有预分配比预分配更快!

于 2013-04-17T08:02:38.657 回答
-1

我同意 Ladislav 的观点,即增量时间可能不可靠。但是我不认为现代 PC 需要预先分配,一个简单的浏览器插件会浪费大量内存。我相信 Rebol 垃圾收集器对于普通使用来说已经足够了。(可能在Android设备速度和内存上还是有问题的)

于 2013-04-18T12:33:21.213 回答