GHC是否支持无GC编程?

时间:2018-08-15 20:54:08

标签: haskell garbage-collection ghc

带有-S选项和一个简单程序:

main = do
   print "Hello"
   main

我可以看到它会产生一些垃圾:

[...]
  1024232      4904     45992  0.000  0.000    0.428    0.530    0    0  (Gen:  1)
        0                      0.000  0.000

   1,242,080,056 bytes allocated in the heap
         271,656 bytes copied during GC
[...] 

但是删除print后,显然没有。是否有可用于编写无GC程序的核心库的无分配子集?

编辑:最近也有关于线性类型的工作,似乎有可能启用这种功能。

1 个答案:

答案 0 :(得分:7)

您有时可能会生成执行几乎没有垃圾收集的小型程序。例如,以下程序:

main = print $ sum [(1::Int)..1000000000]

如果使用-O2进行编译,则应在不分配太多内存或执行任何值得提及的GC的情况下运行。

但是,这通常仅限于可以使用“未装箱”数据类型(在这种情况下,未装箱的Int#值)编译成没有代数数据结构(在这种情况下,列表是融合的)的紧密循环的程序不存在)。有限的一组更复杂的数据结构(例如,未装箱的Vector)也可以在不分配的情况下进行操作,如果您非常小心,则可以编写无需分配就可以对此类结构进行操作的算法很多。

例如,以下程序:

import Control.Monad
import qualified Data.Vector.Unboxed.Mutable as V

main :: IO ()
main = do
  v <- V.new 1000000
  forM_ [0..999999] $ \i -> do
    V.write v i i
  replicateM_ 999 $
    forM_ [0..499999] $ \i -> do
      V.swap v i (999999 - i)
  print =<< V.read v 123

分配一百万个整数的数组,然后对它进行999次反转所有元素。

与GHC版本8.4.3和-O2一起编译时,它在开始时分配了大约8个演出,但是在运行列表反转时不做任何其他分配。我的猜测是,您可以使用类似的技术来实现有用的功能,例如就地快速排序,而无需进行任何分配,因此可以跳过任何GC。

但是,作为一般规则,分配是GHC编译的Haskell代码实际运行方式的基本组成部分,因此没有合理的库或编程技术子集可以保证无GC编程。