Benchmark.hs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. {-# LANGUAGE ExistentialQuantification #-}
  2. {-# LANGUAGE NamedFieldPuns #-}
  3. import Control.Applicative hiding (optional, many)
  4. import Control.Monad
  5. import System.Directory
  6. import Text.ParserCombinators.ReadP
  7. import Data.Char
  8. import Data.List
  9. import Text.PrettyPrint hiding (char)
  10. import Text.Printf
  11. import Data.Monoid
  12. import System.Environment
  13. type Bytes = Integer
  14. type MegaBytes = Integer
  15. type Seconds = Float
  16. type Percent = Float
  17. type BytesPerSecond = Bytes
  18. type Metas = Integer
  19. data Statistics = Stats
  20. { command :: String
  21. , memoryInUse :: MegaBytes
  22. , totalTime :: Seconds
  23. , numberOfMetas :: Metas
  24. , attemptedConstraints :: Integer
  25. , maxMetas :: Integer
  26. , maxConstraints :: Integer
  27. }
  28. instance Show Statistics where
  29. show (Stats _ mem time meta cs maxMeta maxCs) =
  30. printf "%6.2fs - %4dMB - %5d (%3d) metas - %5d (%3d) constraints" time mem meta maxMeta cs maxCs
  31. noStats = Stats "true" 0 0
  32. notP :: ReadP a -> ReadP ()
  33. notP p = do
  34. s <- look
  35. case readP_to_S p s of
  36. [] -> return ()
  37. _ -> pfail
  38. -- Greedy version of many
  39. many' :: ReadP a -> ReadP [a]
  40. many' p = many p <* notP p
  41. orElse :: ReadP a -> ReadP a -> ReadP a
  42. orElse p q = p +++ (notP p *> q)
  43. munchTo :: Char -> ReadP String
  44. munchTo c = munch (c /=) <* char c
  45. lineP :: ReadP String
  46. lineP = munchTo '\n'
  47. integerP :: ReadP Integer
  48. integerP = do
  49. skipSpaces
  50. s <- filter (/=',') <$> munch1 (`elem` (',':['0'..'9']))
  51. guard (not $ null s)
  52. return $ read s
  53. bytesP :: ReadP Bytes
  54. bytesP = integerP <* skipSpaces <* string "bytes"
  55. megaBytesP :: ReadP MegaBytes
  56. megaBytesP = integerP <* skipSpaces <* (string "Mb" +++ string "MB" +++ string "MiB")
  57. floatP :: ReadP Float
  58. floatP = do
  59. skipSpaces
  60. s <- munch1 (`elem` ('.':['0'..'9']))
  61. return $ read s
  62. timeP :: ReadP Seconds
  63. timeP = floatP <* char 's'
  64. percentP :: ReadP Percent
  65. percentP = floatP <* char '%'
  66. metaP :: ReadP Metas
  67. metaP = munchTo ':' *> integerP <* string " metas" <* lineP
  68. collectionP :: ReadP (Integer, Seconds)
  69. collectionP = (,) <$> integerP <* munchTo '(' <*> timeP <* lineP
  70. data Ticks = Tick String Integer
  71. deriving (Show)
  72. tickP = Tick <$> label <*> integerP <* lineP
  73. where
  74. label = unwords <$> many (munch (== ' ') *> munch1 (not . isSpace))
  75. ticksP =
  76. string "Accumulated statistics" *> lineP *> many' tickP
  77. statsP :: ReadP Statistics
  78. statsP = do
  79. ticks <- ticksP `orElse` return []
  80. let numberOfMetas = sum [ n | Tick "metas" n <- ticks ]
  81. attemptedConstraints = sum [ n | Tick "attempted-constraints" n <- ticks ]
  82. maxMetas = maximum $ 0 : [ n | Tick "max-open-metas" n <- ticks ]
  83. maxConstraints = maximum $ 0 : [ n | Tick "max-open-constraints" n <- ticks ]
  84. command <- lineP
  85. many lineP
  86. memoryInUse <- skipSpaces *> megaBytesP <* skipSpaces <* string "total memory" <* lineP
  87. let timeReport s = skipSpaces *> string s *> skipSpaces *> string "time" *> timeP <* lineP
  88. many lineP
  89. totalTime <- timeReport "Total"
  90. many lineP
  91. return $ Stats
  92. { command
  93. , memoryInUse
  94. , totalTime
  95. , numberOfMetas
  96. , attemptedConstraints
  97. , maxMetas
  98. , maxConstraints
  99. }
  100. file = "logs/ulf-norells-macbook-pro-20081126-12.59/syntax1"
  101. runReadP p s =
  102. case readP_to_S p s of
  103. (x, _):_ -> x
  104. [] -> error $ "no parse:\n" ++ s
  105. parseFile file = do
  106. s <- readFile file
  107. case readP_to_S statsP s of
  108. (stats, s'):_ -> return stats
  109. [] -> error $ "no parse: " ++ file ++ "\n" ++ s
  110. isProperFile ('.':_) = False
  111. isProperFile "README" = False
  112. isProperFile _ = True
  113. dirContents dir = filter isProperFile <$> getDirectoryContents dir
  114. logDirs :: IO [FilePath]
  115. logDirs = dirContents "logs"
  116. logs :: IO [Log]
  117. logs = map read <$> logDirs
  118. readLogs :: Log -> IO [(FilePath, Statistics)]
  119. readLogs l = do
  120. let dir = "logs/" ++ logDir l
  121. xs <- dirContents dir
  122. mapM (\s -> (,) s <$> parseFile (dir ++ "/" ++ s)) xs
  123. data Log = Log { machine :: String
  124. , timeStamp :: String
  125. }
  126. deriving (Show)
  127. logDir :: Log -> FilePath
  128. logDir (Log m t) = t ++ "-" ++ m
  129. instance Read Log where
  130. readsPrec _ = readP_to_S $ do
  131. d <- count 8 $ satisfy isDigit
  132. char '-'
  133. hh <- count 2 $ satisfy isDigit
  134. char '.'
  135. mm <- count 2 $ satisfy isDigit
  136. char '-'
  137. m <- many1 get
  138. return $ Log m (d ++ "-" ++ hh ++ "." ++ mm)
  139. data Attr = forall a. Show a => Attr String (Statistics -> a)
  140. stats :: (Log -> Bool) -> (FilePath -> Bool) -> [Attr] -> IO ()
  141. stats goodLog goodCase attrs = do
  142. ls <- filter goodLog <$> logs
  143. mapM_ printStat ls
  144. where
  145. printStat l = do
  146. putStrLn $ logDir l
  147. cs <- filter (goodCase . fst) <$> readLogs l
  148. let w = maximum $ 0 : [ length name | (name, _) <- cs ]
  149. print $ vcat $ map (prAttrs w) cs
  150. prAttrs w (c, s) = nest 2 $ text (pad c) <+> vcat (map (prAttr s) attrs)
  151. where
  152. pad s = s ++ replicate (w - length s) ' ' ++ ":"
  153. prAttr s (Attr name f) = text (show (f s))
  154. time = stats (const True) (const True) [Attr "time" totalTime]
  155. mem = stats (const True) (const True) [Attr "space" memoryInUse]
  156. summary = stats (const True) (const True) [Attr "stats" id]
  157. main = do
  158. args <- getArgs
  159. case args of
  160. [] -> summary
  161. [l] -> stats ((l `isInfixOf`) . logDir) (const True) [Attr "stats" id]
  162. _ -> do
  163. prog <- getProgName
  164. putStrLn $ "Usage: " ++ prog ++ " [LOG]"