【问题标题】:Avoiding the garbage collection避免垃圾收集
【发布时间】:2013-11-24 13:03:46
【问题描述】:

https://stackoverflow.com/a/15243682/944430

然后是编码:使用未装箱类型(无 GC),最小化惰性结构分配。以打包形式保存长期存在的数据。测试和基准测试。

1.) 什么是未装箱类型?我很确定他说的是数据类型,比如Just xIO y(盒装)。但是新类型呢?如果我理解正确的话,newtype 根本没有开销,因此不应该算作盒装类型?

2.) 他所说的Keep long lived data around in packed form. 是什么意思?

3.) 我还能做些什么来防止 GC 暂停?

【问题讨论】:

    标签: haskell garbage-collection


    【解决方案1】:

    1 . 未装箱的类型是 Haskell 中的原语。例如,Int 定义为:data Int = GHC.Types.I# GHC.Prim.Int#(用于 GHC 编译器)。尾随 # 符号用于表示原语(这只是约定)。 Haskell 中并不存在原语。您不能定义其他原语。当它们出现在代码中时,编译器负责将它们转换为“真正的”函数调用(函数也可以是原语)和数据类型。

    是的,newtype 不会另外“装箱”一个类型。但是你不能有一个包含原语的新类型——newtype Int2 = Int2 Int# 无效,而data Int2 = Int2 Int# 很好。

    在您链接的问题的上下文中,原始类型和盒装类型之间的主要区别在于它们在内存中的表示方式。原始类型意味着没有可遵循的指针。指向 Int# 的指针 必须 指向数字的值,而指向 Int 的指针可能指向指向 thunk 的 thunk ... 等等。请注意,这意味着原语总是严格的。如果您认为这将是一个问题,请使用UNPACK pragma,它会删除任何“中间”装箱。也就是说,

    data D = D (Int, Int)
    

    存储为指向包含两个指针 (Ints) 的内存块的指针 (元组) 的指针 (D),每个指针都指向实际的 Int#。然而,

    data D = D {-# UNPACK #-} !(Int, Int)
    

    存储为指向两个Ints 的指针(D),从而消除了一层装箱。注意!。这表明该字段是严格的并且对于UNPACK 是必需的。

    2 。任何将被多态函数调用的数据都应该被打包,因为传递给多态函数的解包数据无论如何都会被重新打包(引入不必要的开销)。保持长期数据打包的原因是,它更有可能用于需要重新打包的中间数据类型或函数,而使用短期数据更容易控制,短期数据在被传递之前只传递给少数函数垃圾收集。

    3 .在 99% 的情况下,您不会遇到垃圾收集器暂停的问题。通常,您无法保证 GC 不会暂停。我唯一的建议是,不要试图重新发明轮子。有一些库专为具有大量数据(repa、vector 等)的高性能计算而设计。如果您尝试自己实现它,很有可能他们做得更好!

    【讨论】:

    • 您的示例不太正确,它将取消对元组的装箱,但单个 Ints 将被装箱。如果您想要两个原始的Int#s,则必须使用data D = D {-# UNPACK #-} !Int {-# UNPACK #-} !Int(或-funbox-strict-fields)。
    【解决方案2】:

    如果您定义data Int2 = Int,您可以认为Int# 是未装箱的,普通Int 是装箱的,Int2 是“双装箱”。您是否使用newtype 而不是data,它会避免一种间接方式。但是Int 本身仍然是盒装的。因此Int2 也被装箱了。

    至于packed form,不赘述,直观上类似于这种C代码。

    struct PackedCoordinate {
       int x;
       int y;
    }
    
    struct UnpackedCoordinate {
       int *x;
       int *y;
    }
    

    我不确定他为什么建议将长期存在的数据采用打包形式。无论如何,从我链接到的文档看来,应该小心使用{-# UNPACK #-} pragma,因为如果你不走运,GHC 可能需要在函数调用之前重新打包它的值,使其分配的内存比它分配的内存多一开始就没有解压。

    为了避免垃圾收集。我认为您应该将其视为与分析相关的任何其他事情:找到程序中的瓶颈,然后从那里开始工作。


    附言。请评论我碰巧不正确的任何事情。 :)

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-15
    • 1970-01-01
    • 1970-01-01
    • 2011-01-21
    • 2023-03-21
    • 1970-01-01
    • 2018-12-30
    相关资源
    最近更新 更多