我在一个拥有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周期?