@@ -3,7 +3,7 @@ module Stats (
3
3
addStats ,
4
4
finaliseStats ,
5
5
timed ,
6
- microsWithUnit ,
6
+ secWithUnit ,
7
7
RequestStats (.. ),
8
8
StatsVar ,
9
9
MethodTiming (.. ),
@@ -25,7 +25,7 @@ import Booster.Log
25
25
import Booster.Prettyprinter
26
26
import Kore.JsonRpc.Types (APIMethod )
27
27
28
- -- server statistics
28
+ -- | Statistics for duration measurement time series (in seconds)
29
29
data RequestStats a = RequestStats
30
30
{ count :: Int
31
31
, average :: a
@@ -60,31 +60,30 @@ instance (Floating a, PrintfArg a, Ord a) => Pretty (RequestStats a) where
60
60
<+> withUnit stats. koreMax
61
61
]
62
62
where
63
- withUnit = pretty . microsWithUnit
63
+ withUnit = pretty . secWithUnit
64
64
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
70
70
71
71
-- internal helper type
72
- -- all values are in microseconds
73
- data Stats' a = Stats'
72
+ -- all values are in seconds
73
+ data Stats' = Stats'
74
74
{ 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
81
81
}
82
82
83
- instance ( Ord a , Num a ) => Semigroup ( Stats' a ) where
83
+ instance Semigroup Stats' where
84
84
(<>) = addStats'
85
85
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'
88
87
addStats' stats1 stats2 =
89
88
Stats'
90
89
{ count = stats1. count + stats2. count
@@ -96,7 +95,7 @@ addStats' stats1 stats2 =
96
95
, koreMax = max stats1. koreMax stats2. koreMax
97
96
}
98
97
99
- singleStats' :: Num a => a -> a -> Stats' a
98
+ singleStats' :: Double -> Double -> Stats'
100
99
singleStats' x korePart =
101
100
Stats'
102
101
{ count = 1
@@ -108,43 +107,44 @@ singleStats' x korePart =
108
107
, koreMax = korePart
109
108
}
110
109
111
- type StatsVar = MVar (Map APIMethod ( Stats' Double ) )
110
+ type StatsVar = MVar (Map APIMethod Stats' )
112
111
113
112
-- 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 }
115
114
deriving stock (Eq , Show , Generic )
116
115
deriving
117
116
(ToJSON , FromJSON )
118
- via CustomJSON '[FieldLabelModifier '[CamelToKebab ]] ( MethodTiming a )
117
+ via CustomJSON '[FieldLabelModifier '[CamelToKebab ]] MethodTiming
119
118
120
- instance ToLogFormat ( MethodTiming Double ) where
119
+ instance ToLogFormat MethodTiming where
121
120
toTextualLog mt =
122
121
pack $
123
122
printf
124
123
" Performed %s in %s (%s kore time)"
125
124
(show mt. method)
126
- (microsWithUnit mt. time)
127
- (microsWithUnit mt. koreTime)
125
+ (secWithUnit mt. time)
126
+ (secWithUnit mt. koreTime)
128
127
toJSONLog = toJSON
129
128
130
129
addStats ::
131
130
MonadIO m =>
132
- MVar (Map APIMethod ( Stats' Double ) ) ->
133
- MethodTiming Double ->
131
+ MVar (Map APIMethod Stats' ) ->
132
+ MethodTiming ->
134
133
m ()
135
134
addStats statVar MethodTiming {method, time, koreTime} =
136
135
liftIO . modifyMVar_ statVar $
137
136
pure . Map. insertWith (<>) method (singleStats' time koreTime)
138
137
139
- newStats :: MonadIO m => m (MVar (Map APIMethod ( Stats' Double ) ))
138
+ newStats :: MonadIO m => m (MVar (Map APIMethod Stats' ))
140
139
newStats = liftIO $ newMVar Map. empty
141
140
141
+ -- returns time taken by the given action (in seconds)
142
142
timed :: MonadIO m => m a -> m (a , Double )
143
143
timed action = do
144
144
start <- liftIO $ getTime Monotonic
145
145
result <- action
146
146
stop <- liftIO $ getTime Monotonic
147
- let time = fromIntegral (toNanoSecs (diffTimeSpec stop start)) / 1000.0
147
+ let time = fromIntegral (toNanoSecs (diffTimeSpec stop start)) / 10 ** 9
148
148
pure (result, time)
149
149
150
150
newtype FinalStats = FinalStats (Map APIMethod (RequestStats Double ))
@@ -164,10 +164,10 @@ instance ToLogFormat FinalStats where
164
164
toTextualLog = renderText . pretty
165
165
toJSONLog = toJSON
166
166
167
- finaliseStats :: MVar (Map APIMethod ( Stats' Double ) ) -> IO FinalStats
167
+ finaliseStats :: MVar (Map APIMethod Stats' ) -> IO FinalStats
168
168
finaliseStats var = FinalStats . Map. map finalise <$> readMVar var
169
169
where
170
- finalise :: Floating a => Stats' a -> RequestStats a
170
+ finalise :: Stats' -> RequestStats Double
171
171
finalise Stats' {count, total, squares, maxVal, minVal, koreTotal, koreMax} =
172
172
let average = total / fromIntegral count
173
173
stddev = sqrt $ squares / fromIntegral count - average * average
0 commit comments