packages feed

ghc-time-alloc-prof 0.0.0.1 → 0.1.0

raw patch · 5 files changed

+207/−75 lines, 5 filesdep +directorydep +filepathdep +processdep ~attoparsecdep ~basePVP ok

version bump matches the API change (PVP)

Dependencies added: directory, filepath, process, tasty, tasty-hunit, temporary

Dependency ranges changed: attoparsec, base

API changes (from Hackage documentation)

+ GHC.RTS.TimeAllocProfile.Parser: instance GHC.Show.Show GHC.RTS.TimeAllocProfile.Parser.HeaderParams
- GHC.RTS.TimeAllocProfile: BriefCostCentre :: Text -> Text -> Maybe Text -> Double -> Double -> Maybe Integer -> Maybe Integer -> BriefCostCentre
+ GHC.RTS.TimeAllocProfile: BriefCostCentre :: !Text -> !Text -> !(Maybe Text) -> !Double -> !Double -> !(Maybe Integer) -> !(Maybe Integer) -> BriefCostCentre
- GHC.RTS.TimeAllocProfile: CostCentre :: Text -> Text -> Maybe Text -> CostCentreNo -> Integer -> Double -> Double -> Double -> Double -> Maybe Integer -> Maybe Integer -> CostCentre
+ GHC.RTS.TimeAllocProfile: CostCentre :: !Text -> !Text -> !(Maybe Text) -> !CostCentreNo -> !Integer -> !Double -> !Double -> !Double -> !Double -> !(Maybe Integer) -> !(Maybe Integer) -> CostCentre
- GHC.RTS.TimeAllocProfile: TimeAllocProfile :: LocalTime -> Text -> TotalTime -> TotalAlloc -> [BriefCostCentre] -> CostCentreTree -> TimeAllocProfile
+ GHC.RTS.TimeAllocProfile: TimeAllocProfile :: !LocalTime -> !Text -> !TotalTime -> !TotalAlloc -> [BriefCostCentre] -> !CostCentreTree -> TimeAllocProfile
- GHC.RTS.TimeAllocProfile: TotalTime :: DiffTime -> Integer -> DiffTime -> Int -> TotalTime
+ GHC.RTS.TimeAllocProfile: TotalTime :: !DiffTime -> !Integer -> !DiffTime -> !Int -> TotalTime
- GHC.RTS.TimeAllocProfile: [briefCostCentreAlloc] :: BriefCostCentre -> Double
+ GHC.RTS.TimeAllocProfile: [briefCostCentreAlloc] :: BriefCostCentre -> !Double
- GHC.RTS.TimeAllocProfile: [briefCostCentreBytes] :: BriefCostCentre -> Maybe Integer
+ GHC.RTS.TimeAllocProfile: [briefCostCentreBytes] :: BriefCostCentre -> !(Maybe Integer)
- GHC.RTS.TimeAllocProfile: [briefCostCentreModule] :: BriefCostCentre -> Text
+ GHC.RTS.TimeAllocProfile: [briefCostCentreModule] :: BriefCostCentre -> !Text
- GHC.RTS.TimeAllocProfile: [briefCostCentreName] :: BriefCostCentre -> Text
+ GHC.RTS.TimeAllocProfile: [briefCostCentreName] :: BriefCostCentre -> !Text
- GHC.RTS.TimeAllocProfile: [briefCostCentreSrc] :: BriefCostCentre -> Maybe Text
+ GHC.RTS.TimeAllocProfile: [briefCostCentreSrc] :: BriefCostCentre -> !(Maybe Text)
- GHC.RTS.TimeAllocProfile: [briefCostCentreTicks] :: BriefCostCentre -> Maybe Integer
+ GHC.RTS.TimeAllocProfile: [briefCostCentreTicks] :: BriefCostCentre -> !(Maybe Integer)
- GHC.RTS.TimeAllocProfile: [briefCostCentreTime] :: BriefCostCentre -> Double
+ GHC.RTS.TimeAllocProfile: [briefCostCentreTime] :: BriefCostCentre -> !Double
- GHC.RTS.TimeAllocProfile: [costCentreBytes] :: CostCentre -> Maybe Integer
+ GHC.RTS.TimeAllocProfile: [costCentreBytes] :: CostCentre -> !(Maybe Integer)
- GHC.RTS.TimeAllocProfile: [costCentreEntries] :: CostCentre -> Integer
+ GHC.RTS.TimeAllocProfile: [costCentreEntries] :: CostCentre -> !Integer
- GHC.RTS.TimeAllocProfile: [costCentreIndAlloc] :: CostCentre -> Double
+ GHC.RTS.TimeAllocProfile: [costCentreIndAlloc] :: CostCentre -> !Double
- GHC.RTS.TimeAllocProfile: [costCentreIndTime] :: CostCentre -> Double
+ GHC.RTS.TimeAllocProfile: [costCentreIndTime] :: CostCentre -> !Double
- GHC.RTS.TimeAllocProfile: [costCentreInhAlloc] :: CostCentre -> Double
+ GHC.RTS.TimeAllocProfile: [costCentreInhAlloc] :: CostCentre -> !Double
- GHC.RTS.TimeAllocProfile: [costCentreInhTime] :: CostCentre -> Double
+ GHC.RTS.TimeAllocProfile: [costCentreInhTime] :: CostCentre -> !Double
- GHC.RTS.TimeAllocProfile: [costCentreModule] :: CostCentre -> Text
+ GHC.RTS.TimeAllocProfile: [costCentreModule] :: CostCentre -> !Text
- GHC.RTS.TimeAllocProfile: [costCentreName] :: CostCentre -> Text
+ GHC.RTS.TimeAllocProfile: [costCentreName] :: CostCentre -> !Text
- GHC.RTS.TimeAllocProfile: [costCentreNo] :: CostCentre -> CostCentreNo
+ GHC.RTS.TimeAllocProfile: [costCentreNo] :: CostCentre -> !CostCentreNo
- GHC.RTS.TimeAllocProfile: [costCentreSrc] :: CostCentre -> Maybe Text
+ GHC.RTS.TimeAllocProfile: [costCentreSrc] :: CostCentre -> !(Maybe Text)
- GHC.RTS.TimeAllocProfile: [costCentreTicks] :: CostCentre -> Maybe Integer
+ GHC.RTS.TimeAllocProfile: [costCentreTicks] :: CostCentre -> !(Maybe Integer)
- GHC.RTS.TimeAllocProfile: [profileCommandLine] :: TimeAllocProfile -> Text
+ GHC.RTS.TimeAllocProfile: [profileCommandLine] :: TimeAllocProfile -> !Text
- GHC.RTS.TimeAllocProfile: [profileCostCentreTree] :: TimeAllocProfile -> CostCentreTree
+ GHC.RTS.TimeAllocProfile: [profileCostCentreTree] :: TimeAllocProfile -> !CostCentreTree
- GHC.RTS.TimeAllocProfile: [profileTimestamp] :: TimeAllocProfile -> LocalTime
+ GHC.RTS.TimeAllocProfile: [profileTimestamp] :: TimeAllocProfile -> !LocalTime
- GHC.RTS.TimeAllocProfile: [profileTotalAlloc] :: TimeAllocProfile -> TotalAlloc
+ GHC.RTS.TimeAllocProfile: [profileTotalAlloc] :: TimeAllocProfile -> !TotalAlloc
- GHC.RTS.TimeAllocProfile: [profileTotalTime] :: TimeAllocProfile -> TotalTime
+ GHC.RTS.TimeAllocProfile: [profileTotalTime] :: TimeAllocProfile -> !TotalTime
- GHC.RTS.TimeAllocProfile: [totalTimeElapsed] :: TotalTime -> DiffTime
+ GHC.RTS.TimeAllocProfile: [totalTimeElapsed] :: TotalTime -> !DiffTime
- GHC.RTS.TimeAllocProfile: [totalTimeProcessors] :: TotalTime -> Int
+ GHC.RTS.TimeAllocProfile: [totalTimeProcessors] :: TotalTime -> !Int
- GHC.RTS.TimeAllocProfile: [totalTimeResolution] :: TotalTime -> DiffTime
+ GHC.RTS.TimeAllocProfile: [totalTimeResolution] :: TotalTime -> !DiffTime
- GHC.RTS.TimeAllocProfile: [totalTimeTicks] :: TotalTime -> Integer
+ GHC.RTS.TimeAllocProfile: [totalTimeTicks] :: TotalTime -> !Integer
- GHC.RTS.TimeAllocProfile.Parser: briefCostCentre :: Parser BriefCostCentre
+ GHC.RTS.TimeAllocProfile.Parser: briefCostCentre :: HeaderParams -> Parser BriefCostCentre
- GHC.RTS.TimeAllocProfile.Parser: costCentre :: Parser CostCentre
+ GHC.RTS.TimeAllocProfile.Parser: costCentre :: HeaderParams -> Parser CostCentre
- GHC.RTS.TimeAllocProfile.Types: BriefCostCentre :: Text -> Text -> Maybe Text -> Double -> Double -> Maybe Integer -> Maybe Integer -> BriefCostCentre
+ GHC.RTS.TimeAllocProfile.Types: BriefCostCentre :: !Text -> !Text -> !(Maybe Text) -> !Double -> !Double -> !(Maybe Integer) -> !(Maybe Integer) -> BriefCostCentre
- GHC.RTS.TimeAllocProfile.Types: CostCentre :: Text -> Text -> Maybe Text -> CostCentreNo -> Integer -> Double -> Double -> Double -> Double -> Maybe Integer -> Maybe Integer -> CostCentre
+ GHC.RTS.TimeAllocProfile.Types: CostCentre :: !Text -> !Text -> !(Maybe Text) -> !CostCentreNo -> !Integer -> !Double -> !Double -> !Double -> !Double -> !(Maybe Integer) -> !(Maybe Integer) -> CostCentre
- GHC.RTS.TimeAllocProfile.Types: TimeAllocProfile :: LocalTime -> Text -> TotalTime -> TotalAlloc -> [BriefCostCentre] -> CostCentreTree -> TimeAllocProfile
+ GHC.RTS.TimeAllocProfile.Types: TimeAllocProfile :: !LocalTime -> !Text -> !TotalTime -> !TotalAlloc -> [BriefCostCentre] -> !CostCentreTree -> TimeAllocProfile
- GHC.RTS.TimeAllocProfile.Types: TotalTime :: DiffTime -> Integer -> DiffTime -> Int -> TotalTime
+ GHC.RTS.TimeAllocProfile.Types: TotalTime :: !DiffTime -> !Integer -> !DiffTime -> !Int -> TotalTime
- GHC.RTS.TimeAllocProfile.Types: [briefCostCentreAlloc] :: BriefCostCentre -> Double
+ GHC.RTS.TimeAllocProfile.Types: [briefCostCentreAlloc] :: BriefCostCentre -> !Double
- GHC.RTS.TimeAllocProfile.Types: [briefCostCentreBytes] :: BriefCostCentre -> Maybe Integer
+ GHC.RTS.TimeAllocProfile.Types: [briefCostCentreBytes] :: BriefCostCentre -> !(Maybe Integer)
- GHC.RTS.TimeAllocProfile.Types: [briefCostCentreModule] :: BriefCostCentre -> Text
+ GHC.RTS.TimeAllocProfile.Types: [briefCostCentreModule] :: BriefCostCentre -> !Text
- GHC.RTS.TimeAllocProfile.Types: [briefCostCentreName] :: BriefCostCentre -> Text
+ GHC.RTS.TimeAllocProfile.Types: [briefCostCentreName] :: BriefCostCentre -> !Text
- GHC.RTS.TimeAllocProfile.Types: [briefCostCentreSrc] :: BriefCostCentre -> Maybe Text
+ GHC.RTS.TimeAllocProfile.Types: [briefCostCentreSrc] :: BriefCostCentre -> !(Maybe Text)
- GHC.RTS.TimeAllocProfile.Types: [briefCostCentreTicks] :: BriefCostCentre -> Maybe Integer
+ GHC.RTS.TimeAllocProfile.Types: [briefCostCentreTicks] :: BriefCostCentre -> !(Maybe Integer)
- GHC.RTS.TimeAllocProfile.Types: [briefCostCentreTime] :: BriefCostCentre -> Double
+ GHC.RTS.TimeAllocProfile.Types: [briefCostCentreTime] :: BriefCostCentre -> !Double
- GHC.RTS.TimeAllocProfile.Types: [costCentreBytes] :: CostCentre -> Maybe Integer
+ GHC.RTS.TimeAllocProfile.Types: [costCentreBytes] :: CostCentre -> !(Maybe Integer)
- GHC.RTS.TimeAllocProfile.Types: [costCentreEntries] :: CostCentre -> Integer
+ GHC.RTS.TimeAllocProfile.Types: [costCentreEntries] :: CostCentre -> !Integer
- GHC.RTS.TimeAllocProfile.Types: [costCentreIndAlloc] :: CostCentre -> Double
+ GHC.RTS.TimeAllocProfile.Types: [costCentreIndAlloc] :: CostCentre -> !Double
- GHC.RTS.TimeAllocProfile.Types: [costCentreIndTime] :: CostCentre -> Double
+ GHC.RTS.TimeAllocProfile.Types: [costCentreIndTime] :: CostCentre -> !Double
- GHC.RTS.TimeAllocProfile.Types: [costCentreInhAlloc] :: CostCentre -> Double
+ GHC.RTS.TimeAllocProfile.Types: [costCentreInhAlloc] :: CostCentre -> !Double
- GHC.RTS.TimeAllocProfile.Types: [costCentreInhTime] :: CostCentre -> Double
+ GHC.RTS.TimeAllocProfile.Types: [costCentreInhTime] :: CostCentre -> !Double
- GHC.RTS.TimeAllocProfile.Types: [costCentreModule] :: CostCentre -> Text
+ GHC.RTS.TimeAllocProfile.Types: [costCentreModule] :: CostCentre -> !Text
- GHC.RTS.TimeAllocProfile.Types: [costCentreName] :: CostCentre -> Text
+ GHC.RTS.TimeAllocProfile.Types: [costCentreName] :: CostCentre -> !Text
- GHC.RTS.TimeAllocProfile.Types: [costCentreNo] :: CostCentre -> CostCentreNo
+ GHC.RTS.TimeAllocProfile.Types: [costCentreNo] :: CostCentre -> !CostCentreNo
- GHC.RTS.TimeAllocProfile.Types: [costCentreSrc] :: CostCentre -> Maybe Text
+ GHC.RTS.TimeAllocProfile.Types: [costCentreSrc] :: CostCentre -> !(Maybe Text)
- GHC.RTS.TimeAllocProfile.Types: [costCentreTicks] :: CostCentre -> Maybe Integer
+ GHC.RTS.TimeAllocProfile.Types: [costCentreTicks] :: CostCentre -> !(Maybe Integer)
- GHC.RTS.TimeAllocProfile.Types: [profileCommandLine] :: TimeAllocProfile -> Text
+ GHC.RTS.TimeAllocProfile.Types: [profileCommandLine] :: TimeAllocProfile -> !Text
- GHC.RTS.TimeAllocProfile.Types: [profileCostCentreTree] :: TimeAllocProfile -> CostCentreTree
+ GHC.RTS.TimeAllocProfile.Types: [profileCostCentreTree] :: TimeAllocProfile -> !CostCentreTree
- GHC.RTS.TimeAllocProfile.Types: [profileTimestamp] :: TimeAllocProfile -> LocalTime
+ GHC.RTS.TimeAllocProfile.Types: [profileTimestamp] :: TimeAllocProfile -> !LocalTime
- GHC.RTS.TimeAllocProfile.Types: [profileTotalAlloc] :: TimeAllocProfile -> TotalAlloc
+ GHC.RTS.TimeAllocProfile.Types: [profileTotalAlloc] :: TimeAllocProfile -> !TotalAlloc
- GHC.RTS.TimeAllocProfile.Types: [profileTotalTime] :: TimeAllocProfile -> TotalTime
+ GHC.RTS.TimeAllocProfile.Types: [profileTotalTime] :: TimeAllocProfile -> !TotalTime
- GHC.RTS.TimeAllocProfile.Types: [totalTimeElapsed] :: TotalTime -> DiffTime
+ GHC.RTS.TimeAllocProfile.Types: [totalTimeElapsed] :: TotalTime -> !DiffTime
- GHC.RTS.TimeAllocProfile.Types: [totalTimeProcessors] :: TotalTime -> Int
+ GHC.RTS.TimeAllocProfile.Types: [totalTimeProcessors] :: TotalTime -> !Int
- GHC.RTS.TimeAllocProfile.Types: [totalTimeResolution] :: TotalTime -> DiffTime
+ GHC.RTS.TimeAllocProfile.Types: [totalTimeResolution] :: TotalTime -> !DiffTime
- GHC.RTS.TimeAllocProfile.Types: [totalTimeTicks] :: TotalTime -> Integer
+ GHC.RTS.TimeAllocProfile.Types: [totalTimeTicks] :: TotalTime -> !Integer

Files

ghc-time-alloc-prof.cabal view
@@ -1,5 +1,5 @@ name: ghc-time-alloc-prof-version: 0.0.0.1+version: 0.1.0 synopsis: Library for parsing GHC time and allocation profiling reports description: Library for parsing GHC time and allocation profiling reports homepage: https://github.com/maoe/ghc-time-alloc-prof@@ -7,10 +7,11 @@ license-file: LICENSE author: Mitsutoshi Aoe maintainer: Mitsutoshi Aoe <maoe@foldr.in>-copyright: Copyright (C) 2013 Mitsutoshi Aoe+copyright: Copyright (C) 2013-2016 Mitsutoshi Aoe category: Development build-type: Simple cabal-version: >=1.10+tested-with: GHC >= 7.6 && <= 8.0.1  flag dump   description: Build the executable "dump"@@ -47,6 +48,26 @@     , ghc-time-alloc-prof     , text   ghc-options: -Wall -rtsopts+  default-language: Haskell2010++test-suite regression+  type: exitcode-stdio-1.0+  hs-source-dirs: tests+  main-is: Regression.hs+  build-depends:+      attoparsec >= 0.10 && < 0.14+    , base+    , directory+    , filepath+    , ghc-time-alloc-prof+    , process+    , tasty < 0.12+    , tasty-hunit >= 0.9.1 && < 0.10+    , temporary+    , text+  ghc-options: -Wall+  if impl(ghc >= 8.0)+    ghc-options: -Wno-unused-imports   default-language: Haskell2010  source-repository head
src/GHC/RTS/TimeAllocProfile/CostCentreTree.hs view
@@ -10,7 +10,7 @@   , buildCostCentresOrderBy   , buildCallSitesOrderBy   ) where-import Control.Applicative ((<$>), (<*>))+import Control.Applicative import Control.Arrow ((&&&)) import Data.Foldable (asum) import Data.Function (on)
src/GHC/RTS/TimeAllocProfile/Parser.hs view
@@ -16,7 +16,7 @@   , costCentre   ) where import Control.Applicative-import Control.Monad (void)+import Control.Monad import Data.Char (isSpace) import Data.Foldable (asum, foldl') import Data.Sequence (Seq, (><), (|>))@@ -38,7 +38,7 @@  timeAllocProfile :: Parser TimeAllocProfile timeAllocProfile = do-  skipSpace+  skipHorizontalSpace   profileTimestamp <- timestamp; skipSpace   void title; skipSpace   profileCommandLine <- commandLine; skipSpace@@ -47,16 +47,16 @@   profileHotCostCentres <- hotCostCentres; skipSpace   profileCostCentreTree <- costCentres; skipSpace   endOfInput-  return TimeAllocProfile {..}+  return $! TimeAllocProfile {..}  timestamp :: Parser LocalTime timestamp = do-  void parseDayOfTheWeek; skipSpace+  parseDayOfTheWeek >> skipSpace   month <- parseMonth; skipSpace   day <- parseDay; skipSpace   tod <- parseTimeOfDay; skipSpace   year <- parseYear; skipSpace-  return LocalTime+  return $! LocalTime     { localDay = fromGregorian year month day     , localTimeOfDay = tod     }@@ -92,7 +92,7 @@     <$> decimal <* string " ticks @ "     <*> picoSeconds <* string ", "     <*> decimal <* many1 (notChar ')')-  return TotalTime+  return $! TotalTime     { totalTimeElapsed = elapsed     , totalTimeTicks = ticks     , totalTimeResolution = picosecondsToDiffTime resolution@@ -108,50 +108,85 @@  totalAlloc :: Parser TotalAlloc totalAlloc = do-  void $ string "total alloc ="; skipSpace-  n <- groupedDecimal-  void $ string " bytes"; skipSpace+  string "total alloc =" >> skipSpace+  !n <- groupedDecimal+  string " bytes" >> skipSpace   parens $ void $ string "excludes profiling overheads"   return TotalAlloc { totalAllocBytes = n }   where-    groupedDecimal = foldl' go 0 <$> decimal `sepBy` char ','+    groupedDecimal = do+      ds <- decimal `sepBy` char ','+      return $! foldl' go 0 ds       where         go z n = z * 1000 + n +newtype HeaderParams = HeaderParams+  { headerHasSrc :: Bool -- ^ SRC column exists+  } deriving Show++header :: Parser HeaderParams+header = do+  optional_ $ do+    string "individual" >> skipHorizontalSpace+    string "inherited" >> skipSpace+  string "COST CENTRE" >> skipHorizontalSpace+  string "MODULE" >> skipHorizontalSpace+  headerHasSrc <- option False $ True <$ string "SRC"; skipHorizontalSpace+  optional_ $ string "no." >> skipHorizontalSpace+  optional_ $ string "entries" >> skipHorizontalSpace+  string "%time" >> skipHorizontalSpace+  string "%alloc" >> skipHorizontalSpace+  optional_ $ do+    string "%time" >> skipHorizontalSpace+    string "%alloc" >> skipHorizontalSpace+  optional_ $ do+    string "ticks" >> skipHorizontalSpace+    string "bytes" >> skipHorizontalSpace+  return HeaderParams+    {..}+ hotCostCentres :: Parser [BriefCostCentre]-hotCostCentres =-  header *> skipSpace *> many1 (briefCostCentre <* skipSpace)-  where-    header = A.takeWhile $ not . isEndOfLine+hotCostCentres = do+  params <- header; skipSpace+  briefCostCentre params `sepBy1` endOfLine -briefCostCentre :: Parser BriefCostCentre-briefCostCentre = BriefCostCentre-  <$> symbol <* skipSpace -- name-  <*> symbol <* skipSpace -- module-  <*> optional symbol <* skipSpace -- src-  <*> double <* skipSpace -- %time-  <*> double <* skipSpace -- %alloc-  <*> optional decimal <* skipSpace -- ticks-  <*> optional decimal -- bytes+briefCostCentre :: HeaderParams -> Parser BriefCostCentre+briefCostCentre HeaderParams {..} = BriefCostCentre+  <$> symbol <* skipHorizontalSpace -- name+  <*> symbol <* skipHorizontalSpace -- module+  <*> source <* skipHorizontalSpace -- src+  <*> double <* skipHorizontalSpace -- %time+  <*> double <* skipHorizontalSpace -- %alloc+  <*> optional decimal <* skipHorizontalSpace -- ticks+  <*> optional decimal <* skipHorizontalSpace -- bytes+  where+    source+      | headerHasSrc = Just <$> symbol+      | otherwise = pure Nothing  costCentres :: Parser CostCentreTree-costCentres = header *> skipSpace *> costCentreTree-  where-    !header = count 2 $ A.takeWhile (not . isEndOfLine) <* skipSpace+costCentres = do+  params <- header; skipSpace+  costCentreTree params -costCentre :: Parser CostCentre-costCentre = do-  name <- symbol; skipSpace-  modName <- symbol; skipSpace-  src <- optional symbol; skipSpace-  no <- decimal; skipSpace-  entries <- decimal; skipSpace-  indTime <- double; skipSpace-  indAlloc <- double; skipSpace-  inhTime <- double; skipSpace-  inhAlloc <- double;+costCentre :: HeaderParams -> Parser CostCentre+costCentre HeaderParams {..} = do+  name <- symbol; skipHorizontalSpace+  modName <- symbol; skipHorizontalSpace+  src <- if headerHasSrc+    then do+      !sym <- symbol+      return $! Just sym+    else pure Nothing+  skipHorizontalSpace+  no <- decimal; skipHorizontalSpace+  entries <- decimal; skipHorizontalSpace+  indTime <- double; skipHorizontalSpace+  indAlloc <- double; skipHorizontalSpace+  inhTime <- double; skipHorizontalSpace+  inhAlloc <- double; skipHorizontalSpace   optInfo <- optional optionalInfo-  return CostCentre+  return $! CostCentre     { costCentreName = name     , costCentreModule = modName     , costCentreSrc = src@@ -166,16 +201,19 @@     }   where     optionalInfo = do-      skipSpace-      ticks <- decimal; skipSpace-      bytes <- decimal+      !ticks <- decimal+      skipHorizontalSpace+      !bytes <- decimal       return (ticks, bytes) -costCentreTree :: Parser CostCentreTree-costCentreTree = buildTree <$> costCentreList+costCentreTree :: HeaderParams -> Parser CostCentreTree+costCentreTree params = buildTree <$> costCentreList   where     costCentreList = nestedCostCentre `sepBy1` endOfLine-    nestedCostCentre = (,) <$> nestLevel <*> costCentre+    nestedCostCentre = (,)+      <$> nestLevel+      <*> costCentre params+      <* skipHorizontalSpace     nestLevel = howMany space  type Level = Int@@ -228,3 +266,9 @@  symbol :: Parser Text symbol = A.takeWhile $ not . isSpace++skipHorizontalSpace :: Parser ()+skipHorizontalSpace = void $ A.takeWhile isHorizontalSpace++optional_ :: Parser a -> Parser ()+optional_ = void . optional
src/GHC/RTS/TimeAllocProfile/Types.hs view
@@ -2,30 +2,31 @@ module GHC.RTS.TimeAllocProfile.Types where import Data.IntMap (IntMap) import Data.Map (Map)-import Data.Monoid (mempty)+import Data.Monoid import Data.Text (Text) import Data.Time (DiffTime, LocalTime) import Data.Sequence (Seq)+import Prelude  -- | Top-level profiling report data TimeAllocProfile = TimeAllocProfile-  { profileTimestamp :: LocalTime-  , profileCommandLine :: Text-  , profileTotalTime :: TotalTime-  , profileTotalAlloc :: TotalAlloc+  { profileTimestamp :: !LocalTime+  , profileCommandLine :: !Text+  , profileTotalTime :: !TotalTime+  , profileTotalAlloc :: !TotalAlloc   , profileHotCostCentres :: [BriefCostCentre]-  , profileCostCentreTree :: CostCentreTree+  , profileCostCentreTree :: !CostCentreTree   } deriving Show  -- | @total time@ in the profiling reports data TotalTime = TotalTime-  { totalTimeElapsed :: DiffTime+  { totalTimeElapsed :: !DiffTime   -- ^ Total elapsed time in seconds-  , totalTimeTicks :: Integer+  , totalTimeTicks :: !Integer   -- ^ Total number of ticks-  , totalTimeResolution :: DiffTime+  , totalTimeResolution :: !DiffTime   -- ^ Duration of a tick-  , totalTimeProcessors :: Int+  , totalTimeProcessors :: !Int   -- ^ Number of processors   } deriving Show @@ -36,47 +37,47 @@   } deriving Show  data BriefCostCentre = BriefCostCentre-  { briefCostCentreName :: Text+  { briefCostCentreName :: !Text   -- ^ Name of the cost-centre-  , briefCostCentreModule :: Text+  , briefCostCentreModule :: !Text   -- ^ Module name of the cost-centre-  , briefCostCentreSrc :: Maybe Text+  , briefCostCentreSrc :: !(Maybe Text)   -- ^ Source location of the cost-centre-  , briefCostCentreTime :: Double+  , briefCostCentreTime :: !Double   -- ^ Total time spent in the cost-centre-  , briefCostCentreAlloc :: Double+  , briefCostCentreAlloc :: !Double   -- ^ Total allocation in the cost-centre-  , briefCostCentreTicks :: Maybe Integer+  , briefCostCentreTicks :: !(Maybe Integer)   -- ^ Total ticks in the cost-centre. This number exists only if   -- @-P@ or @-Pa@ option is given at run-time.-  , briefCostCentreBytes :: Maybe Integer+  , briefCostCentreBytes :: !(Maybe Integer)   -- ^ Total memory allocation in the cost-centre. This number   -- exists only if @-P@ or @-Pa@ option is given at run-time.   } deriving Show  -- | Cost-centre node data CostCentre = CostCentre-  { costCentreName :: Text+  { costCentreName :: !Text   -- ^ Name of the cost-centre-  , costCentreModule :: Text+  , costCentreModule :: !Text   -- ^ Module name of the cost-centre-  , costCentreSrc :: Maybe Text+  , costCentreSrc :: !(Maybe Text)   -- ^ Source location of the cost-centre-  , costCentreNo :: CostCentreNo+  , costCentreNo :: !CostCentreNo   -- ^ Identifier of the cost-centre-  , costCentreEntries :: Integer+  , costCentreEntries :: !Integer   -- ^ Number of entries to the cost-centre-  , costCentreIndTime :: Double+  , costCentreIndTime :: !Double   -- ^ Time spent in the cost-centre itself-  , costCentreIndAlloc :: Double+  , costCentreIndAlloc :: !Double   -- ^ Allocation incurred by the cost-centre itself-  , costCentreInhTime :: Double+  , costCentreInhTime :: !Double   -- ^ Time spent in the cost-centre's children-  , costCentreInhAlloc :: Double+  , costCentreInhAlloc :: !Double   -- ^ Allocation incurred by the cost-centre's children-  , costCentreTicks :: Maybe Integer+  , costCentreTicks :: !(Maybe Integer)   -- ^ Number of ticks in the cost-centre.-  , costCentreBytes :: Maybe Integer+  , costCentreBytes :: !(Maybe Integer)   -- ^ Number of allocated bytes in the cost-centre.   } deriving Show 
+ tests/Regression.hs view
@@ -0,0 +1,66 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ViewPatterns #-}+module Main where+import Data.Foldable+import Data.Traversable+import Control.Applicative+import Control.Monad+import System.Directory+import System.FilePath+import System.IO+import Prelude++import System.IO.Temp+import System.Process+import Test.Tasty+import Test.Tasty.HUnit+import qualified Data.Text.Lazy.IO as TL+import qualified Data.Attoparsec.Text.Lazy as ATL++import GHC.RTS.TimeAllocProfile++#if !MIN_VERSION_directory(1, 2, 3)+import Control.Exception+#endif++main :: IO ()+main = withSystemTempDirectory "test" $ \dir -> withCurrentDirectory dir $+  defaultMain $ testCaseSteps "Regression tests" $ \step -> do+    step "Generating profiling reports"+    profiles <- generateProfiles+    for_ profiles $ \profile -> do+      step $ "Parsing " ++ profile+      assertProfile profile++generateProfiles :: IO [FilePath]+generateProfiles = do+  withFile "hello.hs" WriteMode $ \h ->+    hPutStrLn h "main = putStrLn \"Hello, World!\""+  void $ readProcess "ghc" ["-prof", "-rtsopts", "-fforce-recomp", "hello.hs"] ""+  for profilingFlags $ \(name, flag) -> do+    void $ readProcess "./hello" ["+RTS", flag, "-RTS"] ""+    let profName = "hello" <.> name <.> "prof"+    renameFile "hello.prof" profName+    return profName++profilingFlags :: [(String, String)]+profilingFlags =+  [ ("standard", "-p")+  , ("detailed", "-P")+  , ("full", "-pa")+  ]++assertProfile :: FilePath -> Assertion+assertProfile path = do+  text <- TL.readFile path+  case ATL.parse timeAllocProfile text of+    ATL.Done {} -> return ()+    ATL.Fail _ _ reason -> assertFailure reason++#if !MIN_VERSION_directory(1, 2, 3)+withCurrentDirectory :: FilePath -> IO a -> IO a+withCurrentDirectory dir io = bracket+  (getCurrentDirectory <* setCurrentDirectory dir)+  (setCurrentDirectory)+  (const io)+#endif