Haskell软实时系统的当前状态

31
我正在考虑在软实时应用程序中使用Haskell。我可能会使用actors。我想知道有没有人了解Haskell实时性的现状。具体而言,GC暂停应用程序是否存在问题。我进行了广泛的谷歌搜索,并找到了许多2年前的讨论,但没有最新的。以下是我找到的一些参考资料: 使用Haskell处理大型实时系统:如何(如果可以)? 像游戏这样的软实时应用程序如何使用Haskell的GC性能? 我读过的许多旧文章都表明情况(当时)被认为正在改善。它有吗?
即使在2年前,也有一些评论表明Haskell应用程序可以调整以可靠地将GC暂停保持在一两毫秒内。这看起来现实吗?

我并没有看到GC暂停会对xmonad或者frag产生影响。性能分析工具足以确保你没有产生大量的垃圾数据。 - Don Stewart
我会对 Haskell 中的 actors 有点谨慎,因为 GHC 线程更好研究。 - Don Stewart
我认为这个问题很难以经验主义的方式回答,但是作为一个数据点,我经常在相当标准的商品硬件上的软实时应用程序中看到亚毫秒级别的垃圾回收暂停。 - John L
4个回答

33

因此,“实时”的问题在于GC回收引入的延迟。

GHC使用多核垃圾回收器(还有一个分支带有每个线程本地堆)。最初开发旨在提高多核性能(每个核心可以独立收集),通过减少频繁的停止-全球同步的成本,这也有助于软实时的原因。然而,截至2013年,尽管并行GC已经实现了,但每个线程的本地堆尚未合并到主GHC中。

对于游戏,您应该能够利用这一点,通过使用线程,从而减少需要停止全球本地集合的需求。

对于全局堆中的长寿命对象,您仍然面临一些(毫秒级)的垃圾回收风险。但是,通过例如ThreadScope的仔细分析,可以消除这里的障碍。我曾经看到过通过GHC管理的网络堆栈实时流传1080p视频而没有明显的GC暂停。
即使没有进行这些调整,事情也“可能只是有效的”。 Frag几乎不需要优化,而且现在已经是软实时近10年了。
最后,有许多工具和GHC标志可用于提高性能:

然后是编程:使用非托管类型(无GC),尽量减少惰性结构分配。将长期存在的数据以紧凑形式保留。进行测试和基准测试。

我认为你会做得很好。


1
在哪个 GHC 版本中引入了这些 per-thread 堆栈? GHC 文档中有没有任何细节?(我尝试过谷歌搜索,但没有找到特别的信息) - Qrilka
2
谢谢你提醒我重新审视这个问题。根据 GHC 状态报告,每个线程的 GC 仍然在一个分支中,而不是在主线中。我已经链接到了报告和状态。 - Don Stewart


2

只要你不把懒惰列表用于所有情况,就不应该遇到GC暂停的问题,我没有遇到过这种问题。

然而,对于多线程应用程序来说,天空并不那么明朗。 GHC仍然没有带有线程优先级的调度程序,如果你将线程用于繁重的后台处理,就很容易使事件循环饿死。


1
我对 GHC 的严格性分析不熟悉(http://www.haskell.org/haskellwiki/Performance/Strictness)。我的理解是,在许多情况下,它会自动地使事情变得严格,包括列表。(假设优化级别足够高。)所以你的意思是我应该确保编码时让 GHC 在适当的地方使事情变得严格? - rlkw1024

1

GHC 8.2.1有一个叫做紧凑区域的功能,可能会很有帮助。

据我理解,它似乎是一种半手动内存管理类型。您可以将长期存储的数据存储在紧凑区域中,垃圾收集器不会对其进行跟踪。如果有任何引用指向紧凑区域中的任何内容,则整个紧凑区域将保持活动状态。一旦该区域中没有任何内容的引用,它将被释放。如果您对区域内容进行功能更新,则可以在新区域中重新分配它,并释放旧区域。

http://ezyang.com/compact.html
https://hackage.haskell.org/package/compact-0.1.0.1/docs/Data-Compact.html


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接