问与答 性能-如何在Haskell中获得对5GB堆的控制?

wesley · 2020-02-22 20:30:06 · 热度: 13

目前,我正在试验一个用Snap编写的Haskell小型Web服务器,该服务器会加载并向客户端提供大量数据。 而且,我很难控制服务器进程。 在随机时刻,该进程占用大量CPU数秒至数分钟,并且对客户端请求无响应。 有时,内存使用率会在几秒钟内激增(有时会下降)数百兆字节。

希望有人对长时间运行的Haskell进程有更多的经验,这些进程会占用大量内存,并且可以为我提供一些使事情变得更稳定的指示。 我已经调试了好几天了,在这里我开始感到绝望了。

我的设置的一些概述:

  • 在服务器启动时,我将大约5 GB的数据读入内存中的大型(嵌套)类似Data.Map的结构中。 嵌套映射是值严格的,并且映射内的所有值都是数据类型,其所有字段也都严格。 我花了很多时间来确保不会留下任何未经评估的重击。 导入(取决于我的系统负载)大约需要5-30分钟。 奇怪的是,连续运行中的波动比我预期的要大得多,但这是一个不同的问题。

  • 大数据结构位于“ TVar”内部,由Snap服务器派生的所有客户端线程共享。 客户可以使用一种小的查询语言来请求数据的任意部分。 数据请求量通常很小(最多300kb左右),并且只涉及数据结构的一小部分。 所有只读请求均使用“ readTVarIO”完成,因此它们不需要任何STM事务。

  • 服务器使用以下标志启动:+ RTS -N -I0 -qg -qb。 这将以多线程模式启动服务器,禁用空闲时间和并行GC。 这似乎大大加快了该过程。

服务器大部分运行正常。 但是,不时有一个客户请求超时,CPU峰值达到100%(甚至超过100%),并保持很长一段时间。 同时,服务器不再响应请求。

我能想到的原因很少,可能会导致CPU使用率下降:

  • 该请求仅花费大量时间,因为有很多工作要做。 这有点不太可能,因为有时它会发生在先前运行中被证明非常快的请求中(我指的是20-80ms左右)。

  • 在处理数据并将其发送到客户端之前,仍然需要计算一些未评估的重击。 这也是不太可能的,原因与上一点相同。

  • 垃圾回收以某种方式启动,并开始扫描我的整个5GB堆。 我可以想象这会花费很多时间。

问题是我不知道如何弄清楚到底发生了什么以及如何处理。 因为导入过程花费了很长时间,所以分析结果对我没有任何帮助。 似乎没有办法从代码中有条件地打开和关闭探查器。

我个人怀疑GC是这里的问题。 我正在使用GHC7,它似乎有很多选项可以调整GC的工作方式。

当使用通常具有非常稳定的数据的大堆时,您建议使用哪些GC设置?

猜你喜欢:
共收到 2 条回复
jorge #1 · 2020-02-22 20:30:06

大内存使用和偶尔的CPU高峰几乎肯定是GC介入的。您可以通过使用-F之类的RTS选项来查看是否确实是这种情况,每当有一个主要集合-t时,它将导致GHC发出蜂鸣声,之后它将告诉您统计信息 事实(尤其是查看GC时间是否真的很长)或-Dg,这将打开GC调用的调试信息(尽管您需要使用-debug进行编译)。

您可以采取几种措施来缓解此问题:

  • 在最初导入数据时,GHC浪费了大量时间来增加堆。 您可以通过指定一个大的-F告诉它立即获取您需要的所有内存。

  • 具有稳定数据的大堆将升级为老一代。 如果使用-F增加世代数,则可以使稳定数据处于最古老的GC世代中,而在其之上则具有更传统的年轻和古老堆。

  • 根据应用程序其余部分的内存使用情况,您可以使用-F调整多少GHC使旧的代增长,然后再将其回收。 您可能可以调整此参数以收集此垃圾。

  • 如果没有写操作,并且您有一个定义明确的接口,那么可能值得将该内存不由GHC管理(使用C FFI),这样就永远不会有超级GC的机会。

这些都是推测,因此请针对您的特定应用进行测试。

raphael #2 · 2020-02-22 20:30:07

我有一个非常类似的问题,就是有1.5GB的嵌套地图堆。 默认情况下,在闲置GC处于打开状态的情况下,每个GC都会冻结3-4秒,而在闲置GC处于关闭状态(+ RTS -I0)的情况下,经过几百次查询后,我将获得17秒的冻结时间,这导致了客户端时间 出来

我的“解决方案”是首先增加客户端的超时时间,并要求人们容忍,尽管98%的查询大约是500毫秒,但大约2%的查询会变得非常缓慢。 但是,想要一个更好的解决方案,我最终运行了两个负载平衡的服务器,并使其每200个查询就从集群脱机以执行performGC,然后又恢复运行。

更糟的是,这是对原始Python程序的重写,该程序从未遇到过此类问题。 公平地说,我们确实获得了大约40%的性能提升,轻松的并行化和更稳定的代码库。 但是这个讨厌的GC问题...

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册