简体   繁体   English

堆栈的写时复制

[英]Copy-on-write for stacks

How to implement copy-on-write technique for stack management in postfix calculations of big numbers?如何在大数的后缀计算中实现用于堆栈管理的写时复制技术?

I want to optimize my system regarding operations like:我想针对以下操作优化我的系统:

duplicate top of stack
swap the two top elements
copy the second element on stack to the top
rotate the stack making the third element on top
apply n-ary operations on the stack 

A typical operation take a number of parameters from top of stack and leave a number of results instead.一个典型的操作从栈顶获取一些参数并留下一些结果。

My stack is implemented as an array where data grows from low-mem to hi-mem and pointers from hi-mem to low-mem.我的堆栈实现为一个数组,其中数据从低内存增长到高内存,指针从高内存增长到低内存。

As I can see, the problem is not in the copy-on-write technique per se, but in memory management and garbage collecting.如我所见,问题不在于写时复制技术本身,而在于 memory 管理和垃圾收集。

In Forth we cannot have operator overloading and should have an explicitly separate set of operations for each class of numbers.在 Forth 中,我们不能有运算符重载,并且应该为每个 class 数字有一组明确的单独的操作。 Then we have two options:那么我们有两个选择:

    1. A set of operations over bigint objects (their handlers), with manual memory management, similar to operations over files, dynamic memory buffers, or other objects.对 bigint 对象(它们的处理程序)的一组操作,使用手动 memory 管理,类似于对文件、动态 memory 缓冲区或其他对象的操作。
    1. A full set of operations including the separate stack, like operations over floating-point numbers, with automatic memory management.包括独立堆栈在内的全套操作,如对浮点数的操作,具有自动 memory 管理。

Note that option (2) contains (1) under the hood.请注意,选项 (2) 在引擎盖下包含 (1)。

Reference counting引用计数

One approach to implement automatic memory management in option (2) is to use a dedicated stack (or maybe two stacks) and reference counting.在选项 (2) 中实现自动 memory 管理的一种方法是使用专用堆栈(或可能两个堆栈)和引用计数。 The stack contains references to objects (buffers).堆栈包含对对象(缓冲区)的引用。 The operations that alter data (like b::1+ ) should make copy of the buffer and replace the reference by a new one if the counter is greater than 1 (otherwise data can be altered in the place).更改数据的操作(例如b::1+ )应该复制缓冲区并在计数器大于 1 时用新的引用替换引用(否则可以在该位置更改数据)。

Placing an item (a reference) to the stack should increase its counter, removing from the stack should decrease its counter.将项目(引用)放入堆栈应增加其计数器,从堆栈中移除应减少其计数器。 When the counter become 0, the buffer should be freed.当计数器变为 0 时,应释放缓冲区。

Such operations like b::dup , b::over increase the counter.b::dupb::over这样的操作会增加计数器。 b::swap doesn't change any counter. b::swap不会改变任何计数器。 b::drop decreases the counter (and frees the buffer if the counter is 0). b::drop减少计数器(如果计数器为 0,则释放缓冲区)。

Moving an item from the stack into a bigint variable should not change the counter in the result.将项目从堆栈移动到 bigint 变量不应更改结果中的计数器。 But the counter for the previous value of the variable (if any) should be decreased.但是应该减少变量先前值(如果有)的计数器。

If named variables and constants are not enough (eg, to have user-defined arrays), you may need to introduce into the API the pointers (a kind of anonymous variables) or handlers to bigint objects.如果命名变量和常量还不够(例如,拥有用户定义的数组),您可能需要在 API 中引入指向 bigint 对象的指针(一种匿名变量)或处理程序。

Immutable objects不可变对象

Another approach to implement option (2) is to have immutable objects and garbage collection loop.实现选项 (2) 的另一种方法是使用不可变对象和垃圾回收循环。 In this approach we don't need to count references, but need to maintain the list of external pointers (including variables).在这种方法中,我们不需要计算引用,但需要维护外部指针(包括变量)的列表。

A simple example of such garbage collection can be found in the implementation of s-expressions by Peter Sovietov: Функциональное программирование на языке Форт ("Functional programming in Forth language" in Russian, but it can be easy translated using Google Translate ).此类垃圾收集的一个简单示例可以在彼得苏维埃夫的 s 表达式实现中找到: Функциональное программирование на языке Форт (俄语中的“Functional programming in Forth language”,但可以使用谷歌翻译轻松翻译)。

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

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