ghc-datasize 0.1.2 → 0.2.7
raw patch · 2 files changed
Files
- ghc-datasize.cabal +12/−11
- src/GHC/DataSize.hs +44/−21
ghc-datasize.cabal view
@@ -1,31 +1,32 @@ name: ghc-datasize-version: 0.1.2+version: 0.2.7 license: BSD3 license-file: LICENSE category: GHC, Debug, Development cabal-version: >= 1.10-build-type: Custom-author: Dennis Felsing <dennis@felsin9.de>-maintainer: Dennis Felsing <dennis@felsin9.de>-homepage: http://felsin9.de/nnis/ghc-datasize-copyright: Dennis Felsing 2012+build-type: Simple+author: Dennis Felsing <dennis@felsing.org>+maintainer: Dennis Felsing <dennis@felsing.org>+homepage: https://dennis.felsing.org/ghc-datasize+copyright: Dennis Felsing 2012-2019 synopsis: Determine the size of data structures in GHC's memory description: ghc-datasize is a tool to determine the size of data structures in GHC's memory. Determining the size of recursive data structures is supported. All sizes are in Bytes. -tested-with: GHC == 7.4.2, GHC == 7.6.1, GHC == 7.8.3+tested-with: GHC == 8.6.5 Library Exposed-modules: GHC.DataSize Default-Language: Haskell2010- Build-depends: base == 4.*,- --containers,- ghc-heap-view >= 0.5+ Build-depends: base >= 4.12 && < 5.0,+ deepseq >= 1.3,+ ghc-heap >= 8.0,+ ghc-prim >= 0.5 Hs-source-dirs: src/ Ghc-options: -Wall source-repository head type: git- location: git://r0q.ath.cx/ghc-datasize+ location: https://github.com/def-/ghc-datasize.git
src/GHC/DataSize.hs view
@@ -1,42 +1,39 @@-{-# LANGUAGE CPP #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE UnboxedTuples #-}+ {- | Module : GHC.DataSize Copyright : (c) Dennis Felsing License : 3-Clause BSD-style- Maintainer : dennis@felsin9.de+ Maintainer : dennis@felsing.org -} module GHC.DataSize ( closureSize,- recursiveSize- --mSize+ recursiveSize,+ recursiveSizeNF ) where -import GHC.HeapView hiding (size)+import Control.DeepSeq (NFData, ($!!)) +import GHC.Exts+import GHC.Exts.Heap hiding (size)+import GHC.Exts.Heap.Constants (wORD_SIZE)+ import Control.Monad import System.Mem --- This used to be available via GHC.Constants-#include "MachDeps.h"-wORD_SIZE :: Int-wORD_SIZE = SIZEOF_HSWORD----import qualified Data.IntMap as IntMap----depth :: Int---depth = 10^10- -- Inspired by Simon Marlow: -- https://ghcmutterings.wordpress.com/2009/02/12/53/ -- | Calculate size of GHC objects in Bytes. Note that an object may not be -- evaluated yet and only the size of the initial closure is returned.-closureSize :: Num b => a -> IO b+closureSize :: a -> IO Word closureSize x = do- (_,y,_) <- getClosureRaw x- return . fromIntegral $ length y * wORD_SIZE+ rawWds <- getClosureRawWords x+ return . fromIntegral $ length rawWds * wORD_SIZE -- | Calculate the recursive size of GHC objects in Bytes. Note that the actual -- size in memory is calculated, so shared values are only counted once.@@ -56,16 +53,42 @@ -- -- A garbage collection is performed before the size is calculated, because -- the garbage collector would make heap walks difficult.+--+-- This function works very quickly on small data structures, but can be slow+-- on large and complex ones. If speed is an issue it's probably possible to+-- get the exact size of a small portion of the data structure and then+-- estimate the total size from that. -recursiveSize :: Num b => a -> IO b+recursiveSize :: a -> IO Word recursiveSize x = do performGC liftM snd $ go ([], 0) $ asBox x- where go (vs, acc) b@(Box y) = do+ where go (!vs, !acc) b@(Box y) = do isElem <- liftM or $ mapM (areBoxesEqual b) vs if isElem then return (vs, acc) else do size <- closureSize y closure <- getClosureData y- foldM go (b : vs, acc + size) $ allPtrs closure+ foldM go (b : vs, acc + size) $ allClosures closure++-- | Calculate the recursive size of GHC objects in Bytes after calling+-- Control.DeepSeq.force on the data structure to force it into Normal Form.+-- Using this function requires that the data structure has an `NFData`+-- typeclass instance.++recursiveSizeNF :: NFData a => a -> IO Word+recursiveSizeNF x = recursiveSize $!! x++-- | Adapted from 'GHC.Exts.Heap.getClosureRaw' which isn't exported.+--+-- This returns the raw words of the closure on the heap. Once back in the+-- Haskell world, the raw words that hold pointers may be outdated after a+-- garbage collector run.+getClosureRawWords :: a -> IO [Word]+getClosureRawWords x = do+ case unpackClosure# x of+ (# _iptr, dat, _pointers #) -> do+ let nelems = (I# (sizeofByteArray# dat)) `div` wORD_SIZE+ end = fromIntegral nelems - 1+ pure [W# (indexWordArray# dat i) | I# i <- [0.. end] ]