weigh 0.0.15 → 0.0.16
raw patch · 5 files changed
+69/−24 lines, 5 files
Files
- CHANGELOG +3/−1
- README.md +4/−0
- src/Weigh.hs +55/−21
- src/Weigh/GHCStats.hs +6/−1
- weigh.cabal +1/−1
CHANGELOG view
@@ -1,4 +1,6 @@-0.0.15:+0.0.16:+ * Add MaxOS parameter to indicate memory in use by RTS+ * Add haddock docmentation to the 'Column' type * Fix bug in treating words as int, use only Word as reported by GHC. 0.0.14:
README.md view
@@ -2,6 +2,10 @@ Measures the memory usage of a Haskell value or function +# Limitations++* :warning: Turn off the `-threaded` flag, otherwise it will cause inconsistent results.+ ## Example use ``` haskell
src/Weigh.hs view
@@ -46,6 +46,7 @@ ,defaultConfig -- * Simple combinators ,func+ ,func' ,io ,value ,action@@ -96,7 +97,16 @@ -- Types -- | Table column.-data Column = Case | Allocated | GCs| Live | Check | Max+data Column+ = Case -- ^ Case name for the column+ | Allocated -- ^ Total bytes allocated+ | GCs -- ^ Total number of GCs+ | Live -- ^ Total amount of live data in the heap+ | Check -- ^ Table column indicating about the test status+ | Max -- ^ Maximum residency memory in use+ | MaxOS -- ^ Maximum memory in use by the RTS. Valid only for+ -- GHC >= 8.2.2. For unsupported GHC, this is reported+ -- as 0. deriving (Show, Eq, Enum) -- | Weigh configuration.@@ -121,6 +131,7 @@ ,weightGCs :: !Word32 ,weightLiveBytes :: !Word64 ,weightMaxBytes :: !Word64+ ,weightMaxOSBytes :: !Word64 } deriving (Read,Show) @@ -226,6 +237,15 @@ -> Weigh () func name !f !x = validateFunc name f x (const Nothing) +-- | Weigh a function applied to an argument. Unlike 'func', the argument+-- is evaluated to normal form before the function is applied.+func' :: (NFData a, NFData b)+ => String+ -> (b -> a)+ -> b+ -> Weigh ()+func' name !f (force -> !x) = validateFunc name f x (const Nothing)+ -- | Weigh an action applied to an argument. -- -- Implemented in terms of 'validateAction'.@@ -319,7 +339,7 @@ Just act -> do case act of Action !run arg _ _ -> do- (bytes, gcs, liveBytes, maxByte) <-+ (bytes, gcs, liveBytes, maxByte, maxOSBytes) <- case run of Right f -> weighFunc f arg Left m -> weighAction m arg@@ -332,6 +352,7 @@ , weightGCs = gcs , weightLiveBytes = liveBytes , weightMaxBytes = maxByte+ , weightMaxOSBytes = maxOSBytes })) return Nothing _ -> fmap Just (Traversable.traverse (Traversable.traverse fork) cases)@@ -380,7 +401,7 @@ :: (NFData a) => (b -> a) -- ^ A function whose memory use we want to measure. -> b -- ^ Argument to the function. Doesn't have to be forced.- -> IO (Word64,Word32,Word64,Word64) -- ^ Bytes allocated and garbage collections.+ -> IO (Word64,Word32,Word64,Word64,Word64) -- ^ Bytes allocated and garbage collections. weighFunc run !arg = snd <$> weighFuncResult run arg -- | Weigh a pure function and return the result. This function is heavily@@ -389,7 +410,7 @@ :: (NFData a) => (b -> a) -- ^ A function whose memory use we want to measure. -> b -- ^ Argument to the function. Doesn't have to be forced.- -> IO (a, (Word64,Word32,Word64,Word64)) -- ^ Result, Bytes allocated, GCs.+ -> IO (a, (Word64,Word32,Word64,Word64,Word64)) -- ^ Result, Bytes allocated, GCs. weighFuncResult run !arg = do ghcStatsSizeInBytes <- GHCStats.getGhcStatsSizeInBytes performGC@@ -422,20 +443,24 @@ maxBytes = (GHCStats.maxBytesInUse actionStats `subtracting` GHCStats.maxBytesInUse bootupStats)- return (result, (actualBytes, actionGCs, liveBytes, maxBytes))- where- subtracting x y =- if x > y- then x - y- else 0+ maxOSBytes =+ (GHCStats.maxOSBytes actionStats `subtracting`+ GHCStats.maxOSBytes bootupStats)+ return (result, (actualBytes, actionGCs, liveBytes, maxBytes, maxOSBytes)) +subtracting :: (Ord p, Num p) => p -> p -> p+subtracting x y =+ if x > y+ then x - y+ else 0+ -- | Weigh an IO action. This function is based on `weighActionResult`, which is -- heavily documented inside. weighAction :: (NFData a) => (b -> IO a) -- ^ A function whose memory use we want to measure. -> b -- ^ Argument to the function. Doesn't have to be forced.- -> IO (Word64,Word32,Word64,Word64) -- ^ Bytes allocated and garbage collections.+ -> IO (Word64,Word32,Word64,Word64,Word64) -- ^ Bytes allocated and garbage collections. weighAction run !arg = snd <$> weighActionResult run arg -- | Weigh an IO action, and return the result. This function is heavily@@ -444,7 +469,7 @@ :: (NFData a) => (b -> IO a) -- ^ A function whose memory use we want to measure. -> b -- ^ Argument to the function. Doesn't have to be forced.- -> IO (a, (Word64,Word32,Word64,Word64)) -- ^ Result, Bytes allocated and GCs.+ -> IO (a, (Word64,Word32,Word64,Word64,Word64)) -- ^ Result, Bytes allocated and GCs. weighActionResult run !arg = do ghcStatsSizeInBytes <- GHCStats.getGhcStatsSizeInBytes performGC@@ -459,30 +484,37 @@ !actionStats <- GHCStats.getStats let reflectionGCs = 1 -- We performed an additional GC. actionBytes =- (GHCStats.totalBytesAllocated actionStats -- GHCStats.totalBytesAllocated bootupStats) -+ (GHCStats.totalBytesAllocated actionStats `subtracting`+ GHCStats.totalBytesAllocated bootupStats) `subtracting` -- We subtract the size of "bootupStats", which will be -- included after we did the performGC. fromIntegral ghcStatsSizeInBytes actionGCs =- GHCStats.gcCount actionStats - GHCStats.gcCount bootupStats -+ GHCStats.gcCount actionStats `subtracting` GHCStats.gcCount bootupStats `subtracting` reflectionGCs -- If overheadBytes is too large, we conservatively just -- return zero. It's not perfect, but this library is for -- measuring large quantities anyway. actualBytes = max 0 actionBytes liveBytes =- max 0 (GHCStats.liveBytes actionStats - GHCStats.liveBytes bootupStats)+ max 0 (GHCStats.liveBytes actionStats `subtracting` GHCStats.liveBytes bootupStats) maxBytes = max 0- (GHCStats.maxBytesInUse actionStats -+ (GHCStats.maxBytesInUse actionStats `subtracting` GHCStats.maxBytesInUse bootupStats)+ maxOSBytes =+ max+ 0+ (GHCStats.maxOSBytes actionStats `subtracting`+ GHCStats.maxOSBytes bootupStats) return (result,- ( fromIntegral actualBytes- , fromIntegral actionGCs- , fromIntegral liveBytes- , fromIntegral maxBytes))+ ( actualBytes+ , actionGCs+ , liveBytes+ , maxBytes+ , maxOSBytes+ )) -------------------------------------------------------------------------------- -- Formatting functions@@ -535,6 +567,7 @@ , (Live, (False, "Live")) , (Check, (True, "Check")) , (Max, (False, "Max"))+ , (MaxOS, (False, "MaxOS")) ] toRow (w, err) = [ (Case, (True, takeLastAfterBk $ weightLabel w))@@ -542,6 +575,7 @@ , (GCs, (False, commas (weightGCs w))) , (Live, (False, commas (weightLiveBytes w))) , (Max, (False, commas (weightMaxBytes w)))+ , (MaxOS, (False, commas (weightMaxOSBytes w))) , ( Check , ( True , case err of
src/Weigh/GHCStats.hs view
@@ -10,7 +10,9 @@ ,gcCount ,totalBytesAllocated ,liveBytes- ,maxBytesInUse)+ ,maxBytesInUse+ ,maxOSBytes+ ) where import Data.Word@@ -32,6 +34,9 @@ maxBytesInUse :: RTSStats -> Word64 maxBytesInUse = max_live_bytes++maxOSBytes :: RTSStats -> Word64+maxOSBytes = max_mem_in_use_bytes -- | Get the size of a 'RTSStats' object in bytes. getGhcStatsSizeInBytes :: IO Word64
weigh.cabal view
@@ -1,5 +1,5 @@ name: weigh-version: 0.0.15+version: 0.0.16 synopsis: Measure allocations of a Haskell functions/values description: Please see README.md homepage: https://github.com/fpco/weigh#readme