我的理解是GHC为每个线程提供了一个堆栈.为什么这有必要?GHC不编译到CPS吗?是不是一个简洁地表达为封闭的线程?
您的问题有几个方面.
GHC运行时设计决策的关键参考是论文"多核Haskell的运行时支持".
回想起那个
GHC运行时系统通过将它们多路复用到少数操作系统线程上来支持数百万个轻量级线程,每个物理CPU大约有一个.
和:
每个Haskell线程都在一个有限大小的堆栈上运行,该堆栈在堆中分配.线程的状态及其堆栈保存在堆分配的线程状态对象(TSO)中.TSO的大小约为15个字加上堆栈,构成Haskell线程的整个状态.通过将TSO复制到更大的区域可以增加堆栈,并且可以随后再次收缩
GHC不通过CPS编译.每个线程都进行递归调用,并且它们必须分配给堆栈.通过将堆栈表示为堆分配的对象,事情变得更简单.
一个线程不仅仅是一个闭包.
当一个线程执行时,它开始分配给堆和堆栈.从而:
一个线程的堆栈,因此它的TSO是可变的.当线程执行时,堆栈将累积指向新对象的指针,因此如果TSO驻留在旧代中,则必须将其添加到[记忆GC]的记忆集中.
可以优化堆栈指向的垃圾收集对象,以确保GC与线程在同一物理线程上进行.
此外,当垃圾收集器运行时,非常希望在给定CPU上执行的TSO由同一CPU上的垃圾收集器遍历,因为它引用的TSO和数据可能位于本地缓存中那个CPU.
因此,GHC为每个线程都有一个堆栈,因为编译要求线程可以访问堆栈和堆.通过为每个线程提供自己的堆栈,线程可以更有效地并行执行.线程不仅仅是"闭包",因为它们具有可变堆栈.