惰性求值下如何避免「正确性层面」的空间泄漏
来源: epicandmonicisnotiso.blogspot.com — 2023-04-05
概述
这篇文章回应了上一篇惰性求值文章下读者的疑问:既然承认存在一类关乎正确性的空间泄漏,那该如何避免?作者先给出分类——严格性泄漏(递归函数生成互相依赖的 thunk)、存活性泄漏(大值因被管道的 thunk 引用而无法回收)、过度共享泄漏(生成器被两条管道共享后实现规模被保留)——再逐一给对策。核心工具是把 STG 当作运行模型来读:在 STG 里所有分配(尤其 thunk)在 let 处显式出现,所有求值发生在 case 表达式上,闭包的自由变量被明确列出,因此能看清问题究竟出在哪里。
核心要点
- 三类泄漏:严格性泄漏、存活性泄漏、过度共享泄漏,其中严格性泄漏是局部程序性质。
- 经典例子是 foldl:thunk 被原样传进下一次递归,用 seq 在递归调用前强制求值即可修复。
- 读 STG 能看清 thunk 在哪里分配、在哪里被 case 强制,比手工展开更可靠。
- 严格写 Writer 的 (>>=) 会在末段留下无法用 seq 强制的 thunk,所以别用它,改用日志库。
- 存活性泄漏需要全局规划来避免,通用做法是让每条管道都配一个严格的消费者。
金句
把 STG 这类中间语言当作 Haskell 程序在真实世界里的运行模型。
👍 0
👎 0
返回 Lobsters 首页