@@ -3,7 +3,7 @@ module Stats (
33 addStats ,
44 finaliseStats ,
55 timed ,
6- microsWithUnit ,
6+ secWithUnit ,
77 RequestStats (.. ),
88 StatsVar ,
99 MethodTiming (.. ),
@@ -25,7 +25,7 @@ import Booster.Log
2525import Booster.Prettyprinter
2626import Kore.JsonRpc.Types (APIMethod )
2727
28- -- server statistics
28+ -- | Statistics for duration measurement time series (in seconds)
2929data RequestStats a = RequestStats
3030 { count :: Int
3131 , average :: a
@@ -60,31 +60,30 @@ instance (Floating a, PrintfArg a, Ord a) => Pretty (RequestStats a) where
6060 <+> withUnit stats. koreMax
6161 ]
6262 where
63- withUnit = pretty . microsWithUnit
63+ withUnit = pretty . secWithUnit
6464
65- microsWithUnit :: (Floating a , Ord a , PrintfArg a ) => a -> String
66- microsWithUnit x
67- | x > 10 ** 5 = printf " %.2fs" $ x / 10 ** 6
68- | x > 10 ** 2 = printf " %.3fms" $ x / 10 ** 3
69- | otherwise = printf " %.1fμs" x
65+ secWithUnit :: (Floating a , Ord a , PrintfArg a ) => a -> String
66+ secWithUnit x
67+ | x > 0.1 = printf " %.2fs" x
68+ | x > 0.0001 = printf " %.3fms" $ x * 10 ** 3
69+ | otherwise = printf " %.1fμs" $ x * 10 ** 6
7070
7171-- internal helper type
72- -- all values are in microseconds
73- data Stats' a = Stats'
72+ -- all values are in seconds
73+ data Stats' = Stats'
7474 { count :: Int
75- , total :: a
76- , squares :: a
77- , maxVal :: a
78- , minVal :: a
79- , koreTotal :: a
80- , koreMax :: a
75+ , total :: Double
76+ , squares :: Double
77+ , maxVal :: Double
78+ , minVal :: Double
79+ , koreTotal :: Double
80+ , koreMax :: Double
8181 }
8282
83- instance ( Ord a , Num a ) => Semigroup ( Stats' a ) where
83+ instance Semigroup Stats' where
8484 (<>) = addStats'
8585
86- {-# SPECIALIZE addStats' :: Stats' Double -> Stats' Double -> Stats' Double #-}
87- addStats' :: (Ord a , Num a ) => Stats' a -> Stats' a -> Stats' a
86+ addStats' :: Stats' -> Stats' -> Stats'
8887addStats' stats1 stats2 =
8988 Stats'
9089 { count = stats1. count + stats2. count
@@ -96,7 +95,7 @@ addStats' stats1 stats2 =
9695 , koreMax = max stats1. koreMax stats2. koreMax
9796 }
9897
99- singleStats' :: Num a => a -> a -> Stats' a
98+ singleStats' :: Double -> Double -> Stats'
10099singleStats' x korePart =
101100 Stats'
102101 { count = 1
@@ -108,43 +107,44 @@ singleStats' x korePart =
108107 , koreMax = korePart
109108 }
110109
111- type StatsVar = MVar (Map APIMethod ( Stats' Double ) )
110+ type StatsVar = MVar (Map APIMethod Stats' )
112111
113112-- helper type mainly for json logging
114- data MethodTiming a = MethodTiming { method :: APIMethod , time :: a , koreTime :: a }
113+ data MethodTiming = MethodTiming { method :: APIMethod , time :: Double , koreTime :: Double }
115114 deriving stock (Eq , Show , Generic )
116115 deriving
117116 (ToJSON , FromJSON )
118- via CustomJSON '[FieldLabelModifier '[CamelToKebab ]] ( MethodTiming a )
117+ via CustomJSON '[FieldLabelModifier '[CamelToKebab ]] MethodTiming
119118
120- instance ToLogFormat ( MethodTiming Double ) where
119+ instance ToLogFormat MethodTiming where
121120 toTextualLog mt =
122121 pack $
123122 printf
124123 " Performed %s in %s (%s kore time)"
125124 (show mt. method)
126- (microsWithUnit mt. time)
127- (microsWithUnit mt. koreTime)
125+ (secWithUnit mt. time)
126+ (secWithUnit mt. koreTime)
128127 toJSONLog = toJSON
129128
130129addStats ::
131130 MonadIO m =>
132- MVar (Map APIMethod ( Stats' Double ) ) ->
133- MethodTiming Double ->
131+ MVar (Map APIMethod Stats' ) ->
132+ MethodTiming ->
134133 m ()
135134addStats statVar MethodTiming {method, time, koreTime} =
136135 liftIO . modifyMVar_ statVar $
137136 pure . Map. insertWith (<>) method (singleStats' time koreTime)
138137
139- newStats :: MonadIO m => m (MVar (Map APIMethod ( Stats' Double ) ))
138+ newStats :: MonadIO m => m (MVar (Map APIMethod Stats' ))
140139newStats = liftIO $ newMVar Map. empty
141140
141+ -- returns time taken by the given action (in seconds)
142142timed :: MonadIO m => m a -> m (a , Double )
143143timed action = do
144144 start <- liftIO $ getTime Monotonic
145145 result <- action
146146 stop <- liftIO $ getTime Monotonic
147- let time = fromIntegral (toNanoSecs (diffTimeSpec stop start)) / 1000.0
147+ let time = fromIntegral (toNanoSecs (diffTimeSpec stop start)) / 10 ** 9
148148 pure (result, time)
149149
150150newtype FinalStats = FinalStats (Map APIMethod (RequestStats Double ))
@@ -164,10 +164,10 @@ instance ToLogFormat FinalStats where
164164 toTextualLog = renderText . pretty
165165 toJSONLog = toJSON
166166
167- finaliseStats :: MVar (Map APIMethod ( Stats' Double ) ) -> IO FinalStats
167+ finaliseStats :: MVar (Map APIMethod Stats' ) -> IO FinalStats
168168finaliseStats var = FinalStats . Map. map finalise <$> readMVar var
169169 where
170- finalise :: Floating a => Stats' a -> RequestStats a
170+ finalise :: Stats' -> RequestStats Double
171171 finalise Stats' {count, total, squares, maxVal, minVal, koreTotal, koreMax} =
172172 let average = total / fromIntegral count
173173 stddev = sqrt $ squares / fromIntegral count - average * average
0 commit comments