{-# LANGUAGE BangPatterns #-}
module Eventlog.HeapProf (chunk) where
import Prelude hiding (init, lookup, lines, words, drop, length, readFile)
import Data.Text (Text, lines, init, drop, length, isPrefixOf, unpack, words, pack)
import Data.Text.IO (readFile)
import Data.Attoparsec.Text (parseOnly, double)
import qualified Data.Map as Map
import Eventlog.Total
import Eventlog.Types
chunk :: FilePath -> IO ProfData
chunk f = do
(ph, fs) <- chunkT <$> readFile f
let (counts, totals) = total fs
binfo = Map.mapWithKey (\(Bucket k) (t,s) -> BucketInfo k Nothing t s ) totals
return (ProfData (ph counts) binfo mempty fs [])
chunkT :: Text -> (Int -> Header, [Frame])
chunkT s =
let ls = lines s
(hs, ss) = splitAt 4 ls
[job, date, smpU, valU] =
zipWith header [sJOB, sDATE, sSAMPLE_UNIT, sVALUE_UNIT] hs
fs = chunkSamples ss
in (
Header job date Nothing (pack "") smpU valU
, fs
)
header :: Text -> Text -> Text
header name h =
if name `isPrefixOf` h
then init . drop (length name + 2) $ h
else error $ "Parse.header: expected " ++ unpack name
chunkSamples :: [Text] -> [Frame]
chunkSamples [] = []
chunkSamples (x:xs)
| sBEGIN_SAMPLE `isPrefixOf` x =
let (ys, zs) = break (sEND_SAMPLE `isPrefixOf`) xs
in case zs of
[] -> []
(_:ws) -> parseFrame x ys : chunkSamples ws
| otherwise = []
parseFrame :: Text -> [Text] -> Frame
parseFrame l ls =
let !time = sampleTime sBEGIN_SAMPLE l
ss = map parseSample ls
in Frame time ss
parseSample :: Text -> Sample
parseSample s =
let [k,vs] = words s
!v = readDouble vs
in Sample (Bucket k) v
sampleTime :: Text -> Text -> Double
sampleTime name h =
if name `isPrefixOf` h
then readDouble . drop (length name + 1) $ h
else error $ "Parse.sampleTime: expected " ++ unpack name ++ " but got " ++ unpack h
readDouble :: Text -> Double
readDouble s = case parseOnly double s of
Right x -> x
_ -> error $ "Parse.readDouble: no parse " ++ unpack s
sJOB, sDATE, sSAMPLE_UNIT, sVALUE_UNIT, sBEGIN_SAMPLE, sEND_SAMPLE :: Text
sJOB = pack "JOB"
sDATE = pack "DATE"
sSAMPLE_UNIT = pack "SAMPLE_UNIT"
sVALUE_UNIT = pack "VALUE_UNIT"
sBEGIN_SAMPLE = pack "BEGIN_SAMPLE"
sEND_SAMPLE = pack "END_SAMPLE"