Heap profiler doesn't collect samples when process is idle
Consider this program which runs for 10 seconds, mostly blocked in a safe foreign call:
-- hi.hs
{-# LANGUAGE ForeignFunctionInterface #-}
import Foreign.C.Types
import Control.Concurrent
import Control.Monad
foreign import ccall "sleep" c_sleep :: CInt -> IO ()
force_activity = False
main = do
putStrLn "Hello"
when force_activity $ void $ forkIO $ forever $ threadDelay 1000
c_sleep 10
putStrLn "World"
When running with a 10ms sample period, we would expect 1000 samples. However, in practice we see only three:
$ ghc -threaded hi.hs -rtsopts -prof -eventlog
$ time ./hi +RTS -l -i0.01 -p -hc
Hello
World
real 0m10.013s
user 0m0.041s
sys 0m0.172s
$ ghc-events show /home/ben/hi.eventlog | grep 'start heap prof sample'
304981792: start heap prof sample 0
606904028: start heap prof sample 0
10003624192: start heap prof sample 0
This could be considered either a bug or a feature: since there is no activity there is no allocation and consequently the census should be unchanged. However, this behavior can be somewhat surprising.
One might think that setting force_activity=True
would help as it would spur periodic activity. However, even then the number of samples is quite a bit smaller than expected:
$ nix run .#ghc-events -- show /home/ben/hi.eventlog | grep 'start heap prof sample' | wc -l
41
Brought to my attention by @maralorn.