{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE CPP #-}

-- | Calculate the size of GHC.Stats statically.

module Weigh.GHCStats
  (getGhcStatsSizeInBytes
  ,getStats
  ,gcCount
  ,totalBytesAllocated
  ,liveBytes
  ,maxBytesInUse)
  where

#if __GLASGOW_HASKELL__ < 802
import Data.Int
#else
import Data.Int
import Data.Word
#endif
import GHC.Stats
import System.Mem

#if __GLASGOW_HASKELL__ < 802
-- | Get GHC's statistics.
getStats :: IO GCStats
getStats = getGCStats

gcCount :: GCStats -> Int64
gcCount = numGcs

totalBytesAllocated :: GCStats -> Int64
totalBytesAllocated = bytesAllocated

liveBytes :: GCStats -> Int64
liveBytes = currentBytesUsed

maxBytesInUse :: GCStats -> Int64
maxBytesInUse = maxBytesUsed

#else
-- | Get GHC's statistics.
getStats :: IO RTSStats
getStats = getRTSStats

gcCount :: RTSStats -> Word32
gcCount = gcs

totalBytesAllocated :: RTSStats -> Word64
totalBytesAllocated = allocated_bytes

liveBytes :: RTSStats -> Word64
liveBytes = gcdetails_live_bytes . gc

maxBytesInUse :: RTSStats -> Word64
maxBytesInUse = max_live_bytes
#endif

-- | Get the size of a 'RTSStats' object in bytes.
getGhcStatsSizeInBytes :: IO Int64
getGhcStatsSizeInBytes = do
  s1 <- oneGetStats
  s2 <- twoGetStats
  return (fromIntegral (totalBytesAllocated s2 - totalBytesAllocated s1))
  where
    oneGetStats = do
      performGC
      !s <- getStats
      return s
    twoGetStats = do
      performGC
      !_ <- getStats
      !s <- getStats
      return s