+RTS -s reports low maximum residency when using the non-moving GC
I'm trying to reproduce some of these GC benchmarks using the classic "Pusher" program.
The code
module Main (main) where
import qualified Control.Exception as Exception
import qualified Control.Monad as Monad
import qualified Data.ByteString as ByteString
import qualified Data.Map.Strict as Map
data Msg = Msg !Int !ByteString.ByteString
type Chan = Map.Map Int ByteString.ByteString
_N :: Int
_N = 500 * 1000
message :: Int -> Msg
message n = Msg n (ByteString.replicate 1024 (fromIntegral n))
pushMsg :: Chan -> Msg -> IO Chan
pushMsg chan (Msg msgId msgContent) =
Exception.evaluate $
let
inserted = Map.insert msgId msgContent chan
in
if _N < Map.size inserted
then Map.deleteMin inserted
else inserted
main :: IO ()
main = Monad.foldM_ pushMsg Map.empty (map message [1..2000000])
I compile the program with ghc -threaded -rtsopts -O2 pusher.hs
using GHC-8.10-alpha1 from hvr's PPA and run it:
$ ./pusher +RTS -xn -s
6,524,460,200 bytes allocated in the heap
510,389,120 bytes copied during GC
392,148,056 bytes maximum residency (23 sample(s))
109,980,584 bytes maximum slop
1288 MiB total memory in use (0 MB lost due to fragmentation)
Tot time (elapsed) Avg pause Max pause
Gen 0 6822 colls, 0 par 0.826s 0.518s 0.0001s 0.0005s
Gen 1 23 colls, 0 par 0.132s 0.131s 0.0057s 0.0177s
TASKS: 27 (24 bound, 3 peak workers (3 total), using -N1)
SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)
INIT time 0.001s ( 0.001s elapsed)
MUT time 1.780s ( 1.212s elapsed)
GC time 0.958s ( 0.649s elapsed)
EXIT time 0.074s ( 0.079s elapsed)
Total time 2.813s ( 1.940s elapsed)
Alloc rate 3,665,265,491 bytes per MUT second
Productivity 63.3% of total user, 62.4% of total elapsed
Since the program builds a Map
of 500,000 messages of 1024 bytes each, I'd expect a maximum residency of > 500MB. But the RTS reports only slightly less than 400MB.
If I use the default GC, the RTS reports a more reasonable 588MB.