为什么Haskell编译器不能促进确定性内存管理?

时间:2011-08-12 10:27:13

标签: memory-management haskell garbage-collection

有了丰富的类型信息,为什么Haskell运行时无法避免运行GC来清理?应该可以找出所有用法并在编译的代码中插入适当的alloc / release调用,对吗?这样可以避免运行时GC的开销。

5 个答案:

答案 0 :(得分:25)

通过跟踪使用情况,询问函数式编程语言是否可以减少GC是明智的。虽然一些数据是否可以安全丢弃的一般问题是不可判定的(因为有条件的分支),但是更加稳健地工作并找到更多直接释放的机会肯定是合理的。

值得关注的是Martin Hofmann和移动资源保障项目团队的工作,他们将类型导向内存(de / re)分配作为一个主题。然而,使他们的东西工作的东西是Haskell在其类型系统中没有的东西---线性。如果您知道函数的输入数据是 secret ,则可以重新分配它们占用的内存。 MRG的东西特别好,因为它管理一种类型的解除分配和另一种类型的分配之间的实际交换率,这在纯功能外部下变成了良好的老式指针。事实上,许多可爱的简约变异算法(例如指针反转遍历,覆盖尾部指针构造等)可以使用这些技术看起来纯粹功能(并检查讨厌的错误)。

实际上,资源的线性分型给出了一种保守但可机械检查的近似用法分析,可能有助于减少GC。有趣的问题包括如何干净地(有意的副词选择)与通常的持久交易混合这种处理。在我看来,相当多的中间数据结构在递归计算中具有初始单线程阶段,在计算完成之前被共享或丢弃。有可能减少这些过程产生的垃圾。

TL; DR有很好的类型化的使用分析方法可以减少GC,但是Haskell目前只有类型信息错误,对此目的特别有用。

答案 1 :(得分:14)

基于区域的内存管理是C和C ++中的程序员经常手工编程的:分配一块内存(“区域”,“竞技场”等),在其中分配单个数据,使用它们和当你知道不再需要任何个人数据时,最终会释放整个块。 Tofte,Aiken和其他人(包括你们真正与我们各自的同事一起)在90年代工作,表明可以自动地(即“地区推断”)静态地推断区域分配和解除分配点。保证块不会过早释放,并且在实践中,足够早以避免在需要最后一个数据后长时间保留太多内存。例如,区域ML套件是基于区域推断的完整标准ML编译器。在最终版本中,它与区域内垃圾收集相结合:如果静态推断显示存在长寿区域,则在其中使用垃圾收集。你可以得到你的蛋糕并吃它:你有很长的生活数据的垃圾收集,但很多数据像堆栈一样被管理,即使它通常会在堆中结束。

答案 2 :(得分:8)

考虑以下伪代码:

func a = if some_computation a
    then a
    else 0

要在调用a后知道func a是否为垃圾,编译器必须能够知道some_computation a的结果。如果它可以在一般情况下(这需要解决暂停问题)那样做,那么就根本不需要为这个函数发出代码,更不用说垃圾收集了它。类型信息是不够的。

答案 3 :(得分:5)

使用延迟评估确定对象生命周期并不容易。 JHC编译器确实有(有?)区域内存管理,它会在生命周期结束时通过释放来释放内存。

我也很清楚确切的内存管理是什么意思。

答案 4 :(得分:-1)

类型信息主要与编译时间有关,因为内存管理是运行时事物,因此我认为它们彼此无关。