我正在考虑将 Haskell 用于软实时应用程序。我可能会使用演员,因为它的价值。我想知道是否有人对 Haskell 的当前实时状态有所了解。具体来说,GC 暂停应用程序的问题。我在 Google 上进行了广泛的搜索,发现了 2 多年前的大量讨论,但没有最新的。以下是我找到的一些参考资料:
我读过的许多旧资料表明,情况(当时)被认为正在改善。有吗?
即使在 2 多年前,也有一些评论表明 Haskell 应用程序可以调整为可靠地将 GC 暂停时间控制在一两毫秒。这看起来很现实吗?
我正在考虑将 Haskell 用于软实时应用程序。我可能会使用演员,因为它的价值。我想知道是否有人对 Haskell 的当前实时状态有所了解。具体来说,GC 暂停应用程序的问题。我在 Google 上进行了广泛的搜索,发现了 2 多年前的大量讨论,但没有最新的。以下是我找到的一些参考资料:
我读过的许多旧资料表明,情况(当时)被认为正在改善。有吗?
即使在 2 多年前,也有一些评论表明 Haskell 应用程序可以调整为可靠地将 GC 暂停时间控制在一两毫秒。这看起来很现实吗?
所以对“实时”的关注是 GC 集合引入的延迟。
GHC 使用多核垃圾收集器(并且有一个带有每线程本地堆的分支)。最初开发是为了通过降低频繁停止世界同步的成本来提高多核性能(每个核心可以独立收集),出于同样的原因,这恰好也有利于软实时。然而,截至 2013 年,per-thread local heap 尚未合并到 main GHC 中,尽管并行 GC 已经合并。
对于游戏,您应该能够通过使用线程来利用这一点,从而减少对 stop-the-world 本地集合的需求。
对于长期存在的对象,在全局堆中,您仍然冒着一些(毫秒)GC 的风险。但是,使用例如ThreadScope进行仔细分析将消除这里的障碍。我已经看到通过 GHC 管理的网络堆栈流式传输实时 1080p 视频,而没有明显的 GC 暂停。
即使没有这些调整,事情“可能会奏效”。Frag 几乎不需要优化,并且在将近 10 年前的现在是软实时的。
最后,还有许多工具和 GHC 标志可以提高性能:
然后是编码:使用未装箱的类型(无 GC),最小化惰性结构分配。以打包形式保存长期存在的数据。测试和基准测试。
我想你会没事的。
你见过这些:
另外,我建议联系Multicore Garbage Collection with Local Heaps论文 (ISMM 2011) 的作者。
我没有遇到过 GC 暂停的问题,只要你不为所有事情都使用惰性列表,你就不应该产生太多垃圾。
然而,对于多线程应用程序来说,天空并不是那么明亮。GHC 仍然没有具有线程优先级的调度程序,如果您使用线程进行繁重的后台处理,您很容易使您的事件循环饿死。
GHC 8.2.1 有一个名为 Compact Regions 的功能可能会有所帮助。
据我了解,这似乎是一种半手动的内存管理。您可以将长期存在的数据存储在 Compact Region 中,而垃圾收集器不会对其进行跟踪。如果对 Compact Region 中的任何内容有任何引用,则整个 Compact Region 都会保持活动状态。一旦没有对该区域中任何内容的引用,它将被释放。如果您对区域的内容进行功能更新,您可以在新区域中重新分配它,旧区域将被释放。
http://ezyang.com/compact.html
https://hackage.haskell.org/package/compact-0.1.0.1/docs/Data-Compact.html