Hello community, here is the log from the commit of package ghc-weigh for openSUSE:Factory checked in at 2017-06-04 01:56:00 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/ghc-weigh (Old) and /work/SRC/openSUSE:Factory/.ghc-weigh.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ghc-weigh" Sun Jun 4 01:56:00 2017 rev:3 rq:494201 version:0.0.4 Changes: -------- --- /work/SRC/openSUSE:Factory/ghc-weigh/ghc-weigh.changes 2017-04-14 13:37:01.353314519 +0200 +++ /work/SRC/openSUSE:Factory/.ghc-weigh.new/ghc-weigh.changes 2017-06-04 01:56:03.732130042 +0200 @@ -1,0 +2,5 @@ +Wed May 3 08:24:07 UTC 2017 - [email protected] + +- Update to version 0.0.4 with cabal2obs. + +------------------------------------------------------------------- Old: ---- weigh-0.0.3.tar.gz New: ---- weigh-0.0.4.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ ghc-weigh.spec ++++++ --- /var/tmp/diff_new_pack.gRfMtR/_old 2017-06-04 01:56:04.340044157 +0200 +++ /var/tmp/diff_new_pack.gRfMtR/_new 2017-06-04 01:56:04.344043592 +0200 @@ -19,7 +19,7 @@ %global pkg_name weigh %bcond_with tests Name: ghc-%{pkg_name} -Version: 0.0.3 +Version: 0.0.4 Release: 0 Summary: Measure allocations of a Haskell functions/values License: BSD-3-Clause @@ -33,6 +33,7 @@ BuildRequires: ghc-rpm-macros BuildRequires: ghc-split-devel BuildRequires: ghc-template-haskell-devel +BuildRequires: ghc-temporary-devel BuildRoot: %{_tmppath}/%{name}-%{version}-build %description ++++++ weigh-0.0.3.tar.gz -> weigh-0.0.4.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weigh-0.0.3/src/Weigh.hs new/weigh-0.0.4/src/Weigh.hs --- old/weigh-0.0.3/src/Weigh.hs 2016-06-06 18:34:08.000000000 +0200 +++ new/weigh-0.0.4/src/Weigh.hs 2017-04-26 12:25:41.000000000 +0200 @@ -26,6 +26,9 @@ (-- * Main entry points mainWith ,weighResults + -- * Configuration + ,setColumns + ,Column(..) -- * Simple combinators ,func ,io @@ -49,8 +52,9 @@ where import Control.Applicative +import Control.Arrow import Control.DeepSeq -import Control.Monad.Writer +import Control.Monad.State import Data.List import Data.List.Split import Data.Maybe @@ -59,6 +63,8 @@ import Prelude import System.Environment import System.Exit +import System.IO +import System.IO.Temp import System.Mem import System.Process import Text.Printf @@ -67,16 +73,27 @@ -------------------------------------------------------------------------------- -- Types +-- | Table column. +data Column = Case | Allocated | GCs| Live | Check | Max + deriving (Show, Eq, Enum) + +-- | Weigh configuration. +data Config = Config {configColumns :: [Column]} + deriving (Show) + -- | Weigh specification monad. newtype Weigh a = - Weigh {runWeigh :: Writer [(String,Action)] a} + Weigh {runWeigh :: State (Config, [(String,Action)]) a} deriving (Monad,Functor,Applicative) -- | How much a computation weighed in at. data Weight = Weight {weightLabel :: !String ,weightAllocatedBytes :: !Int64 - ,weightGCs :: !Int64} + ,weightGCs :: !Int64 + ,weightLiveBytes :: !Int64 + ,weightMaxBytes :: !Int64 + } deriving (Read,Show) -- | An action to run. @@ -92,10 +109,10 @@ -- | Just run the measuring and print a report. Uses 'weighResults'. mainWith :: Weigh a -> IO () mainWith m = - do results <- weighResults m + do (results, config) <- weighResults m unless (null results) (do putStrLn "" - putStrLn (report results)) + putStrLn (report config results)) case mapMaybe (\(w,r) -> do msg <- r return (w,msg)) @@ -109,23 +126,39 @@ -- | Run the measuring and return all the results, each one may have -- an error. weighResults - :: Weigh a -> IO [(Weight,Maybe String)] -weighResults m = - do args <- getArgs - let cases = execWriter (runWeigh m) - result <- weighDispatch args cases - case result of - Nothing -> return [] - Just weights -> - return (map (\w -> - case lookup (weightLabel w) cases of - Nothing -> (w,Nothing) - Just a -> (w,actionCheck a w)) - weights) + :: Weigh a -> IO ([(Weight,Maybe String)], Config) +weighResults m = do + args <- getArgs + let (config, cases) = + execState (runWeigh m) (defaultConfig, []) + result <- weighDispatch args cases + case result of + Nothing -> return ([], config) + Just weights -> + return + ( map + (\w -> + case lookup (weightLabel w) cases of + Nothing -> (w, Nothing) + Just a -> (w, actionCheck a w)) + weights + , config) -------------------------------------------------------------------------------- -- User DSL +-- | Default columns to display. +defaultColumns :: [Column] +defaultColumns = [Case, Allocated, GCs] + +-- | Default config. +defaultConfig :: Config +defaultConfig = Config {configColumns = defaultColumns} + +-- | Set the config. Default is: 'defaultConfig'. +setColumns :: [Column] -> Weigh () +setColumns cs = Weigh (modify (first (\c -> c {configColumns = cs}))) + -- | Weigh a function applied to an argument. -- -- Implemented in terms of 'validateFunc'. @@ -182,7 +215,7 @@ -> (Weight -> Maybe String) -- ^ A validating function, returns maybe an error. -> Weigh () validateAction name !m !arg !validate = - Weigh (tell [(name,Action (Left m) arg validate)]) + tellAction [(name,Action (Left m) arg validate)] -- | Weigh a function, validating the result validateFunc :: (NFData a) @@ -192,7 +225,11 @@ -> (Weight -> Maybe String) -- ^ A validating function, returns maybe an error. -> Weigh () validateFunc name !f !x !validate = - Weigh (tell [(name,Action (Right f) x validate)]) + tellAction [(name,Action (Right f) x validate)] + +-- | Write out an action. +tellAction :: [(String, Action)] -> Weigh () +tellAction x = Weigh (modify (second ( ++ x))) -------------------------------------------------------------------------------- -- Internal measuring actions @@ -204,19 +241,27 @@ -> IO (Maybe [Weight]) weighDispatch args cases = case args of - ("--case":label:_) -> - case lookup label (deepseq (map fst cases) cases) of - Nothing -> error "No such case!" - Just act -> - do case act of - Action !run arg _ -> - do (bytes,gcs) <- - case run of - Right f -> weighFunc f arg - Left m -> weighAction m arg - print (Weight {weightLabel = label - ,weightAllocatedBytes = bytes - ,weightGCs = gcs}) + ("--case":label:fp:_) -> + let !_ = force fp + in case lookup label (deepseq (map fst cases) cases) of + Nothing -> error "No such case!" + Just act -> do + case act of + Action !run arg _ -> do + (bytes, gcs, liveBytes, maxByte) <- + case run of + Right f -> weighFunc f arg + Left m -> weighAction m arg + writeFile + fp + (show + (Weight + { weightLabel = label + , weightAllocatedBytes = bytes + , weightGCs = gcs + , weightLiveBytes = liveBytes + , weightMaxBytes = maxByte + })) return Nothing _ | names == nub names -> fmap Just (mapM (fork . fst) cases) @@ -227,29 +272,37 @@ fork :: String -- ^ Label for the case. -> IO Weight fork label = - do me <- getExecutablePath - (exit,out,err) <- - readProcessWithExitCode me - ["--case",label,"+RTS","-T","-RTS"] - "" - case exit of - ExitFailure{} -> - error ("Error in case (" ++ show label ++ "):\n " ++ err) - ExitSuccess -> - case reads out of - [(!r,_)] -> return r - _ -> - error (concat ["Malformed output from subprocess. Weigh" - ," (currently) communicates with its sub-" - ,"processes via stdout. Remove any other " - ,"output from your process."]) + withSystemTempFile + "weigh" + (\fp h -> do + hClose h + me <- getExecutablePath + (exit, _, err) <- + readProcessWithExitCode + me + ["--case", label, fp, "+RTS", "-T", "-RTS"] + "" + case exit of + ExitFailure {} -> + error ("Error in case (" ++ show label ++ "):\n " ++ err) + ExitSuccess -> + do out <- readFile fp + case reads out of + [(!r, _)] -> return r + _ -> + error + (concat + [ "Malformed output from subprocess. Weigh" + , " (currently) communicates with its sub-" + , "processes via a temporary file." + ])) -- | Weigh a pure function. This function is heavily documented inside. weighFunc :: (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 (Int64,Int64) -- ^ Bytes allocated and garbage collections. + -> IO (Int64,Int64,Int64,Int64) -- ^ Bytes allocated and garbage collections. weighFunc run !arg = do performGC -- The above forces getGCStats data to be generated NOW. @@ -272,14 +325,17 @@ -- return zero. It's not perfect, but this library is for -- measuring large quantities anyway. actualBytes = max 0 actionBytes - return (actualBytes,actionGCs) + liveBytes = max 0 (currentBytesUsed actionStats - + currentBytesUsed bootupStats) + maxBytes = max 0 (maxBytesUsed actionStats - maxBytesUsed bootupStats) + return (actualBytes,actionGCs,liveBytes, maxBytes) -- | Weigh a pure function. This function 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 (Int64,Int64) -- ^ Bytes allocated and garbage collections. + -> IO (Int64,Int64,Int64,Int64) -- ^ Bytes allocated and garbage collections. weighAction run !arg = do performGC -- The above forces getGCStats data to be generated NOW. @@ -302,32 +358,47 @@ -- return zero. It's not perfect, but this library is for -- measuring large quantities anyway. actualBytes = max 0 actionBytes - return (actualBytes,actionGCs) + liveBytes = max 0 (currentBytesUsed actionStats - + currentBytesUsed bootupStats) + maxBytes = max 0 (maxBytesUsed actionStats - maxBytesUsed bootupStats) + return (actualBytes,actionGCs,liveBytes, maxBytes) -------------------------------------------------------------------------------- -- Formatting functions -- | Make a report of the weights. -report :: [(Weight,Maybe String)] -> String -report = - tablize . - ([(True,"Case"),(False,"Bytes"),(False,"GCs"),(True,"Check")] :) . map toRow - where toRow (w,err) = - [(True,weightLabel w) - ,(False,commas (weightAllocatedBytes w)) - ,(False,commas (weightGCs w)) - ,(True - ,case err of +report :: Config -> [(Weight,Maybe String)] -> String +report config = tablize . (select headings :) . map (select . toRow) + where + select row = mapMaybe (\name -> lookup name row) (configColumns config) + headings = + [ (Case, (True, "Case")) + , (Allocated, (False, "Allocated")) + , (GCs, (False, "GCs")) + , (Live, (False, "Live")) + , (Check, (True, "Check")) + , (Max, (False, "Max")) + ] + toRow (w, err) = + [ (Case, (True, weightLabel w)) + , (Allocated, (False, commas (weightAllocatedBytes w))) + , (GCs, (False, commas (weightGCs w))) + , (Live, (False, commas (weightLiveBytes w))) + , (Max, (False, commas (weightMaxBytes w))) + , ( Check + , ( True + , case err of Nothing -> "OK" - Just{} -> "INVALID")] + Just {} -> "INVALID")) + ] -- | Make a table out of a list of rows. tablize :: [[(Bool,String)]] -> String tablize xs = intercalate "\n" (map (intercalate " " . map fill . zip [0 ..]) xs) - where fill (x',(left,text')) = printf ("%" ++ direction ++ show width ++ "s") text' - where direction = if left + where fill (x',(left',text')) = printf ("%" ++ direction ++ show width ++ "s") text' + where direction = if left' then "-" else "" width = maximum (map (length . snd . (!! x')) xs) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/weigh-0.0.3/weigh.cabal new/weigh-0.0.4/weigh.cabal --- old/weigh-0.0.3/weigh.cabal 2016-06-06 18:38:00.000000000 +0200 +++ new/weigh-0.0.4/weigh.cabal 2017-04-26 12:27:12.000000000 +0200 @@ -1,5 +1,5 @@ name: weigh -version: 0.0.3 +version: 0.0.4 synopsis: Measure allocations of a Haskell functions/values description: Please see README.md homepage: https://github.com/fpco/weigh#readme @@ -30,6 +30,7 @@ , mtl , split , template-haskell + , temporary default-language: Haskell2010 test-suite weigh-test
