使用`threadDelay`时系统调用量过大

时间:2015-12-16 18:43:29

标签: multithreading haskell concurrency garbage-collection ghc

我在一个拥有12个内核的系统上运行了几个Haskell进程。所有进程都使用-threaded进行编译,并运行12个功能。他们都使用的一个库是resource-pool,它保留了一个数据库连接池。

有趣的是,即使所有进程实际上都处于空闲状态,它们也占用了大约2%的CPU时间。使用strace -p $(pgrep processname) -f检查其中一个进程会发现该进程正在执行不合理数量的系统调用,即使它实际上不应该执行任何操作。把事情放在眼里:

  • 使用-N2在进程上运行strace 5秒会生成66K日志文件。
  • 使用(不合理的)-N64运行它会产生60 兆字节日志。

因此,功能的数量会大大增加发出的系统调用量。

深入挖掘我们发现resource-pool正在运行一个收割者线程,它会每秒触发一次,以检查它是否可以清理一些资源。我们可以用这个简单的程序来模拟相同的行为。

module Main where

import Control.Concurrent
import Control.Monad (forever)

main :: IO ()
main = forever $ do
  threadDelay (10 ^ 6)

如果我将-B传递给运行时系统,每当发出GC时都会得到音频反馈,在这种情况下每隔60秒就会收到一次。

因此,当我通过将-I0传递给运行strace命令的RTS来抑制这些GC周期时,只会产生大约70K的大型日志文件。由于该进程还运行scotty服务器,因此在请求进入时会触发GC,因此它们似乎在我实际需要时发生。

由于我们将在明年使用这台机器上大量增加Haskell进程的数量,我想知道如何将他们的空闲时间保持在合理的水平。显然传递-I0似乎是一个相当糟糕的主意(?)。另一个想法是将功能的数量从12减少到类似4的东西。有没有其他方法来调整RTS以便我可以在空闲时保持进程从刻录到多个CPU周期?

0 个答案:

没有答案