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

Pra*_*eep 21 garbage-collection haskell memory-management

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

pig*_*ker 25

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

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

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

TL; DR有很好的类型化的使用分析方法可以减少GC,但是Haskell现在有一种错误的类型信息,对于这个目的特别有用.

  • 你以一定程度的确定性来断言这一点,但是你并没有为我提供一个基础来为自己实现这种确定性.你可能是对的,但你是否愿意扩展导致你获得这种智慧的问题?我知道Clean的唯一性类型并不完全是线性类型系统,但Clean是懒惰的.与此同时,一些异教徒认为Haskell应该在其懒惰中更明确地划定界限,这可能为其他类型的纪律留出空间.我想在这里仍然存在疑问,有了创新. (6认同)
  • 线性不适合懒惰 (2认同)
  • 嗯,我猜这里的"纪律"这个词大致被故意选为"干净".就个人而言,我很快就会将recursive与corecursive代码区别开来,而不是懒惰,但这既不是在这里也不是在那里.与Haskell更直接相关,我想知道是否可以使用更高级别的类型*a la*`runST`来完成某种形式的作用域分配.但这与通过代码分析推断这些属性相反! (2认同)

小智 14

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


Ben*_*Ben 8

考虑以下伪代码:

func a = if some_computation a
    then a
    else 0
Run Code Online (Sandbox Code Playgroud)

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


aug*_*tss 5

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

我也很好奇你的确定性内存管理是什么意思.

  • 我猜测,通过"确定性",他的意思是"激进的"内存管理,换句话说,"在它变得不必要的那一刻就摆脱它",而不是"每当GC检测到它是不必要的时候就把它除掉" . (2认同)