首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何控制Haskell中的5GB堆?

如何控制Haskell中的5GB堆?
EN

Stack Overflow用户
提问于 2011-07-08 10:47:17
回答 2查看 1.6K关注 0票数 48

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

希望有人有更多的经验,长期运行Haskell进程,使用大量的内存,并能给我一些指针,以使事情更加稳定。我已经调试了好几天了,现在我开始有点绝望了。

简要介绍一下我的设置:

  • 在服务器启动时,我将大约5G的数据读入内存中的一个大(嵌套)Data.Map结构中。嵌套的映射是值严格的,映射中的所有值都是数据类型,它们的所有字段也都是严格的。我花了很多时间来确保没有未评估的部分被留下。导入(取决于我的系统负载)大约需要5-30分钟。奇怪的是,连续运行的波动要比我预期的要大得多,但这是一个不同的问题。
  • --大数据结构--存在于由Snap服务器产生的所有客户端线程共享的“TVar”内部。客户端可以使用一种小的查询语言请求数据的任意部分。数据请求的数量通常很小(高达300 or左右),并且只涉及数据结构的一小部分。所有只读请求都是使用“readTVarIO”完成的,因此它们不需要使用以下标志启动任何STM transactions.
  • The服务器:+RTS -N -I0 -qg -qb。这将以多线程模式启动服务器,禁用空闲时间和并行GC.这似乎大大加快了这一进程。

服务器的运行大多没有任何问题。然而,不时有一个客户端请求超时,CPU峰值达到100% (甚至超过100%),并在很长一段时间内一直这样做。同时,服务器不再响应请求。

我认为有几个原因可能导致CPU的使用:

  • 请求只是花费了很多时间,因为有很多工作要做。这在某种程度上是不太可能的,因为在以前的运行中已经证明非常快的请求(我的意思是20-80ms左右)有时会发生这种情况。
  • 仍然有一些未评估的块需要计算,然后才能处理数据并发送到客户端。这也不太可能,与前面的point.
  • Somehow垃圾收集启动并开始扫描整个5GB堆的原因相同。我可以想象这会花费很多时间。--

问题是,我不知道如何确切地搞清楚到底是怎么回事,以及该怎么做。因为导入过程需要这么长的时间,所以分析结果并没有显示出任何有用的东西。似乎没有办法在代码中有条件地打开和关闭分析器。

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

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-07-08 12:45:05

大量的内存使用量和偶尔出现的CPU峰值几乎可以肯定是GC的开始。您可以通过使用RTS选项(如-B )来查看是否确实如此,这会导致GHC在有一个主要集合时发出哔声,-t将在事实发生后告诉您统计信息(特别是查看GC时间是否真的很长)或-Dg,后者打开GC调用的调试信息(尽管您需要用-debug编译)。

为了缓解这个问题,您可以做几件事:

  • 对最初导入的数据,GHC正在浪费大量的时间来增加堆。通过指定一个具有稳定数据的大型-H.
  • A堆,您可以告诉它立即获取所需的所有内存,这将提升到老一代。如果增加了使用it.
  • Depending的代数,您可能能够将稳定的数据放在最古老的、很少由GC生成的数据中,而在应用程序的其他部分的内存使用上,有更多传统的年轻和老堆在-G之上,您可以使用-F来调整在再次收集之前会让老一代增长多少GHC。您可能可以调整这个参数,使这个un垃圾collected.
  • If没有写操作,并且您有一个定义良好的接口,可能值得让这个内存由GHC (使用C)管理,这样就不可能出现超级GC了。

这些都是推测,所以请用您的特定应用程序进行测试。

票数 29
EN

Stack Overflow用户

发布于 2013-10-04 16:56:11

对于一个1.5GB的嵌套映射堆,我有一个非常类似的问题。默认情况下,当空闲GC打开时,我将在每个GC上获得3-4秒的冻结时间,而当空闲GC关闭(+RTS -I0)时,经过几百次查询后,我将得到17秒的冻结,从而导致客户端超时。

我的“解决方案”首先是增加客户端的超时时间,并要求人们容忍这种情况,虽然98%的查询是500 My左右,但大约2%的查询是非常慢的。然而,为了找到更好的解决方案,我最终运行了两台负载平衡服务器,并每200次从集群中将它们从集群中带离线,然后重新运行。

更糟的是,这是对一个原始Python程序的重写,它从未出现过这样的问题。公平地说,我们确实得到了大约40%的性能提高,死胡同的并行化和一个更稳定的代码库。但这个讨厌的GC问题..。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6623391

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档