~ubuntu-branches/ubuntu/jaunty/alex/jaunty

« back to all changes in this revision

Viewing changes to glafp-utils/nofib-analyse/Slurp.hs

  • Committer: Bazaar Package Importer
  • Author(s): Ian Lynagh (wibble)
  • Date: 2003-10-01 12:31:01 UTC
  • Revision ID: james.westby@ubuntu.com-20031001123101-yquo14mvjqh3e0sk
Tags: upstream-2.0
ImportĀ upstreamĀ versionĀ 2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
-----------------------------------------------------------------------------
 
2
-- $Id: Slurp.hs,v 1.4 2002/09/18 12:36:40 simonmar Exp $
 
3
 
 
4
-- (c) Simon Marlow 1997-1999
 
5
-----------------------------------------------------------------------------
 
6
 
 
7
module Slurp (Status(..), Results(..), ResultTable(..), parse_log) where
 
8
 
 
9
import CmdLine
 
10
import FiniteMap
 
11
import RegexString
 
12
import Maybe
 
13
 
 
14
-----------------------------------------------------------------------------
 
15
-- This is the structure into which we collect our results:
 
16
 
 
17
type ResultTable = FiniteMap String Results
 
18
 
 
19
data Status
 
20
        = NotDone
 
21
        | Success
 
22
        | OutOfHeap
 
23
        | OutOfStack
 
24
        | Exit Int
 
25
        | WrongStdout
 
26
        | WrongStderr 
 
27
 
 
28
data Results = Results { 
 
29
        compile_time    :: FiniteMap String Float,
 
30
        module_size     :: FiniteMap String Int,
 
31
        binary_size     :: Maybe Int,
 
32
        link_time       :: Maybe Float,
 
33
        run_time        :: Maybe Float,
 
34
        mut_time        :: Maybe Float,
 
35
        instrs          :: Maybe Integer,
 
36
        mem_reads       :: Maybe Integer,
 
37
        mem_writes      :: Maybe Integer,
 
38
        cache_misses    :: Maybe Integer,
 
39
        gc_work         :: Maybe Integer,
 
40
        gc_time         :: Maybe Float,
 
41
        allocs          :: Maybe Integer,
 
42
        run_status      :: Status,
 
43
        compile_status  :: Status
 
44
        }
 
45
 
 
46
emptyResults = Results { 
 
47
        compile_time    = emptyFM,
 
48
        module_size     = emptyFM,
 
49
        binary_size     = Nothing,
 
50
        link_time       = Nothing,
 
51
        run_time        = Nothing,
 
52
        mut_time        = Nothing,
 
53
        instrs          = Nothing,
 
54
        mem_reads       = Nothing,
 
55
        mem_writes      = Nothing,
 
56
        cache_misses    = Nothing,
 
57
        gc_time         = Nothing,
 
58
        gc_work         = Nothing,
 
59
        allocs          = Nothing,
 
60
        compile_status  = NotDone,
 
61
        run_status      = NotDone
 
62
        }
 
63
 
 
64
-----------------------------------------------------------------------------
 
65
-- Parse the log file
 
66
 
 
67
{-
 
68
Various banner lines:
 
69
 
 
70
==nofib== awards: size of QSort.o follows...
 
71
==nofib== banner: size of banner follows...
 
72
==nofib== awards: time to link awards follows...
 
73
==nofib== awards: time to run awards follows...
 
74
==nofib== boyer2: time to compile Checker follows...
 
75
-}
 
76
 
 
77
banner_re = mkRegex "^==nofib==[ \t]+([A-Za-z0-9_]+):[ \t]+(size of|time to link|time to run|time to compile)[ \t]+([A-Za-z0-9_]+)(\\.o)?[ \t]+follows"
 
78
 
 
79
{-
 
80
This regexp for the output of "time" works on FreeBSD, other versions
 
81
of "time" will need different regexps.
 
82
-}
 
83
 
 
84
time_re = mkRegex "^[ \t]*([0-9.]+)[ \t]+real[ \t]+([0-9.]+)[ \t]+user[ \t]+([0-9.]+)[ \t]+sys[ \t]*$"
 
85
 
 
86
time_gnu17_re = mkRegex "^[ \t]*([0-9.]+)user[ \t]+([0-9.]+)system[ \t]+([0-9.:]+)elapsed"
 
87
                -- /usr/bin/time --version reports: GNU time 1.7
 
88
                -- notice the order is different, and the elapsed time is [hh:]mm:ss.s
 
89
 
 
90
size_re = mkRegex "^[ \t]*([0-9]+)[ \t]+([0-9]+)[ \t]+([0-9]+)"
 
91
 
 
92
{-
 
93
<<ghc: 5820820 bytes, 0 GCs, 0/0 avg/max bytes residency (0 samples), 41087234 bytes GC work, 0.00 INIT (0.05 elapsed), 0.08 MUT (0.18 elapsed), 0.00 GC (0.00 elapsed) :ghc>>
 
94
 
 
95
        = (bytes, gcs, avg_resid, max_resid, samples, gc_work,
 
96
           init, init_elapsed, mut, mut_elapsed, gc, gc_elapsed)
 
97
 
 
98
ghc1_re = pre GHC 4.02
 
99
ghc2_re = GHC 4.02 (includes "xxM in use")
 
100
ghc3_re = GHC 4.03 (includes "xxxx bytes GC work")
 
101
-}
 
102
 
 
103
ghc1_re = mkRegex "^<<ghc:[ \t]+([0-9]+)[ \t]+bytes,[ \t]*([0-9]+)[ \t]+GCs,[ \t]*([0-9]+)/([0-9]+)[ \t]+avg/max bytes residency \\(([0-9]+) samples\\), ([0-9]+) bytes GC work, ([0-9.]+) INIT \\(([0-9.]+) elapsed\\), ([0-9.]+) MUT \\(([0-9.]+) elapsed\\), ([0-9.]+) GC \\(([0-9.]+) elapsed\\) :ghc>>"
 
104
 
 
105
ghc2_re = mkRegex "^<<ghc:[ \t]+([0-9]+)[ \t]+bytes,[ \t]*([0-9]+)[ \t]+GCs,[ \t]*([0-9]+)/([0-9]+)[ \t]+avg/max bytes residency \\(([0-9]+) samples\\), ([0-9]+)M in use, ([0-9.]+) INIT \\(([0-9.]+) elapsed\\), ([0-9.]+) MUT \\(([0-9.]+) elapsed\\), ([0-9.]+) GC \\(([0-9.]+) elapsed\\) :ghc>>"
 
106
 
 
107
ghc3_re = mkRegex "^<<ghc:[ \t]+([0-9]+)[ \t]+bytes,[ \t]*([0-9]+)[ \t]+GCs,[ \t]*([0-9]+)/([0-9]+)[ \t]+avg/max bytes residency \\(([0-9]+) samples\\), ([0-9]+) bytes GC work, ([0-9]+)M in use, ([0-9.]+) INIT \\(([0-9.]+) elapsed\\), ([0-9.]+) MUT \\(([0-9.]+) elapsed\\), ([0-9.]+) GC \\(([0-9.]+) elapsed\\) :ghc>>"
 
108
 
 
109
ghc4_re = mkRegex "^<<ghc-instrs:[ \t]+([0-9]+)[ \t]+bytes,[ \t]*([0-9]+)[ \t]+GCs,[ \t]*([0-9]+)/([0-9]+)[ \t]+avg/max bytes residency \\(([0-9]+) samples\\), ([0-9]+) bytes GC work, ([0-9]+)M in use, ([0-9.]+) INIT \\(([0-9.]+) elapsed\\), ([0-9.]+) MUT \\(([0-9.]+) elapsed\\), ([0-9.]+) GC \\(([0-9.]+) elapsed\\), ([0-9]+) instructions, ([0-9]+) memory reads, ([0-9]+) memory writes, ([0-9]+) L2 cache misses :ghc-instrs>>"
 
110
 
 
111
wrong_exit_status = mkRegex "^\\**[ \t]*expected exit status ([0-9]+) not seen ; got ([0-9]+)"
 
112
 
 
113
wrong_output = mkRegex "^expected (stdout|stderr) not matched by reality$"
 
114
 
 
115
out_of_heap = mkRegex "^\\+ Heap exhausted;$"
 
116
 
 
117
out_of_stack = mkRegex "^\\+ Stack space overflow:"
 
118
 
 
119
parse_log :: String -> ResultTable
 
120
parse_log
 
121
        = combine_results               -- collate information
 
122
        . concat
 
123
        . map process_chunk             -- get information from each chunk
 
124
        . tail                          -- first chunk is junk
 
125
        . chunk_log [] []               -- break at banner lines
 
126
        . lines
 
127
 
 
128
combine_results :: [(String,Results)] -> FiniteMap String Results
 
129
combine_results = foldr f emptyFM
 
130
 where
 
131
        f (prog,results) fm = addToFM_C comb fm prog results
 
132
        comb Results{ compile_time = ct1, link_time = lt1, 
 
133
                      module_size = ms1,
 
134
                      run_time = rt1, mut_time = mt1, 
 
135
                      instrs = is1, mem_reads = mr1, mem_writes = mw1,
 
136
                      cache_misses = cm1,
 
137
                      gc_time = gt1, gc_work = gw1,
 
138
                      binary_size = bs1, allocs = al1, 
 
139
                      run_status = rs1, compile_status = cs1 }
 
140
             Results{ compile_time = ct2, link_time = lt2, 
 
141
                      module_size = ms2,
 
142
                      run_time = rt2, mut_time = mt2,
 
143
                      instrs = is2, mem_reads = mr2, mem_writes = mw2,
 
144
                      cache_misses = cm2,
 
145
                      gc_time = gt2, gc_work = gw2,
 
146
                      binary_size = bs2, allocs = al2, 
 
147
                      run_status = rs2, compile_status = cs2 }
 
148
          =  Results{ compile_time   = plusFM_C const ct1 ct2,
 
149
                      module_size    = plusFM_C const ms1 ms2,
 
150
                      link_time      = combMaybes lt1 lt2,
 
151
                      run_time       = combMaybes rt1 rt2,
 
152
                      mut_time       = combMaybes mt1 mt2,
 
153
                      instrs         = combMaybes is1 is2,
 
154
                      mem_reads      = combMaybes mr1 mr2,
 
155
                      mem_writes     = combMaybes mw1 mw2,
 
156
                      cache_misses   = combMaybes cm1 cm2,
 
157
                      gc_time        = combMaybes gt1 gt2,
 
158
                      gc_work        = combMaybes gw1 gw2,
 
159
                      binary_size    = combMaybes bs1 bs2,
 
160
                      allocs         = combMaybes al1 al2,
 
161
                      run_status     = combStatus rs1 rs2,
 
162
                      compile_status = combStatus cs1 cs2 }
 
163
 
 
164
combMaybes m1 m2 = case maybeToList m1 ++ maybeToList m2 of
 
165
                        [] -> Nothing
 
166
                        (x:_) -> Just x
 
167
 
 
168
combStatus NotDone x = x
 
169
combStatus x NotDone = x
 
170
combStatus x y = x
 
171
 
 
172
chunk_log :: [String] -> [String] -> [String] -> [([String],[String])]
 
173
chunk_log header chunk [] = [(header,chunk)]
 
174
chunk_log header chunk (l:ls) =
 
175
        case matchRegex banner_re l of
 
176
                Nothing -> chunk_log header (l:chunk) ls
 
177
                Just stuff -> (header,chunk) : chunk_log stuff [] ls
 
178
 
 
179
process_chunk :: ([String],[String]) -> [(String,Results)]
 
180
process_chunk (prog : what : mod : _, chk) =
 
181
 case what of
 
182
        "time to compile" -> parse_compile_time prog mod chk
 
183
        "time to run"     -> parse_run_time prog (reverse chk) NotDone
 
184
        "time to link"    -> parse_link_time prog chk
 
185
        "size of"         -> parse_size prog mod chk
 
186
        _                 -> error ("process_chunk: "++what)
 
187
 
 
188
parse_compile_time prog mod [] = []
 
189
parse_compile_time prog mod (l:ls) =
 
190
        case matchRegex time_re l of {
 
191
             Just (real:user:system:_) ->
 
192
                let ct  = addToFM emptyFM mod (read user)
 
193
                in 
 
194
                [(prog,emptyResults{compile_time = ct})];
 
195
             Nothing -> 
 
196
 
 
197
        case matchRegex time_gnu17_re l of {
 
198
             Just (user:system:elapsed:_) ->
 
199
                let ct  = addToFM emptyFM mod (read user)
 
200
                in 
 
201
                [(prog,emptyResults{compile_time = ct})];
 
202
             Nothing -> 
 
203
 
 
204
        case matchRegex ghc1_re l of {
 
205
            Just (allocs:_:_:_:_:init:_:mut:_:gc:_) ->
 
206
              let 
 
207
                  read_mut = read mut
 
208
                  read_gc  = read gc
 
209
                  time = (read init + read_mut + read_gc) :: Float 
 
210
                  ct  = addToFM emptyFM mod time
 
211
              in
 
212
                [(prog,emptyResults{compile_time = ct})];
 
213
            Nothing ->
 
214
 
 
215
        case matchRegex ghc2_re l of {
 
216
           Just (allocs:_:_:_:_:_:init:_:mut:_:gc:_) ->
 
217
              let 
 
218
                  read_mut = read mut
 
219
                  read_gc  = read gc
 
220
                  time = (read init + read_mut + read_gc) :: Float 
 
221
                  ct  = addToFM emptyFM mod time
 
222
              in
 
223
                [(prog,emptyResults{compile_time = ct})];
 
224
            Nothing ->
 
225
 
 
226
        case matchRegex ghc3_re l of {
 
227
           Just (allocs:_:_:_:_:_:_:init:_:mut:_:gc:_) ->
 
228
              let 
 
229
                  read_mut = read mut
 
230
                  read_gc  = read gc
 
231
                  time = (read init + read_mut + read_gc) :: Float 
 
232
                  ct  = addToFM emptyFM mod time
 
233
              in
 
234
                [(prog,emptyResults{compile_time = ct})];
 
235
            Nothing ->
 
236
 
 
237
        case matchRegex ghc4_re l of {
 
238
           Just (allocs:_:_:_:_:_:_:init:_:mut:_:gc:_:_:_:_) ->
 
239
              let 
 
240
                  read_mut = read mut
 
241
                  read_gc  = read gc
 
242
                  time = (read init + read_mut + read_gc) :: Float 
 
243
                  ct  = addToFM emptyFM mod time
 
244
              in
 
245
                [(prog,emptyResults{compile_time = ct})];
 
246
            Nothing ->
 
247
 
 
248
                parse_compile_time prog mod ls
 
249
        }}}}}}
 
250
 
 
251
parse_link_time prog [] = []
 
252
parse_link_time prog (l:ls) =
 
253
          case matchRegex time_re l of {
 
254
             Just (real:user:system:_) ->
 
255
                [(prog,emptyResults{link_time = Just (read user)})];
 
256
             Nothing ->
 
257
 
 
258
          case matchRegex time_gnu17_re l of {
 
259
             Just (user:system:elapsed:_) ->
 
260
                [(prog,emptyResults{link_time = Just (read user)})];
 
261
             Nothing ->
 
262
 
 
263
          parse_link_time prog ls
 
264
          }}
 
265
 
 
266
parse_run_time prog [] NotDone = []
 
267
parse_run_time prog [] ex =[(prog,emptyResults{run_status=ex})]
 
268
parse_run_time prog (l:ls) ex =
 
269
        case matchRegex ghc1_re l of {
 
270
           Just (allocs:_:_:_:_:init:_:mut:_:gc:_) ->
 
271
              let 
 
272
                  read_mut = read mut
 
273
                  read_gc  = read gc
 
274
                  time = (read init + read_mut + read_gc) :: Float 
 
275
              in
 
276
              [(prog,emptyResults{run_time   = Just time,
 
277
                                  mut_time   = Just read_mut,
 
278
                                  gc_time    = Just read_gc,
 
279
                                  allocs     = Just (read allocs),
 
280
                                  run_status = Success })];
 
281
           Nothing -> 
 
282
 
 
283
        case matchRegex ghc2_re l of {
 
284
           Just (allocs:_:_:_:_:_:init:_:mut:_:gc:_) ->
 
285
              let 
 
286
                  read_mut = read mut
 
287
                  read_gc  = read gc
 
288
                  time = (read init + read_mut + read_gc) :: Float 
 
289
              in
 
290
              [(prog,emptyResults{run_time   = Just time,
 
291
                                  mut_time   = Just read_mut,
 
292
                                  gc_time    = Just read_gc,
 
293
                                  allocs     = Just (read allocs),
 
294
                                  run_status = Success })];
 
295
            Nothing ->
 
296
        
 
297
        case matchRegex ghc3_re l of {
 
298
           Just (allocs:_:_:_:_:gc_work:_:init:_:mut:_:gc:_) ->
 
299
              let 
 
300
                  read_mut = read mut
 
301
                  read_gc  = read gc
 
302
                  read_gc_work = read gc_work
 
303
                  time = (read init + read_mut + read_gc) :: Float 
 
304
              in
 
305
              [(prog,emptyResults{run_time   = Just time,
 
306
                                  mut_time   = Just read_mut,
 
307
                                  gc_work    = Just read_gc_work,
 
308
                                  gc_time    = Just read_gc,
 
309
                                  allocs     = Just (read allocs),
 
310
                                  run_status = Success })];
 
311
            Nothing ->
 
312
        
 
313
        case matchRegex ghc4_re l of {
 
314
           Just (allocs:_:_:_:_:gc_work:_:init:_:mut:_:gc:_:is:mem_rs:mem_ws:cache_misses:_) ->
 
315
              let 
 
316
                  read_mut = read mut
 
317
                  read_gc  = read gc
 
318
                  read_gc_work = read gc_work
 
319
                  time = (read init + read_mut + read_gc) :: Float 
 
320
              in
 
321
              [(prog,emptyResults{run_time   = Just time,
 
322
                                  mut_time   = Just read_mut,
 
323
                                  gc_work    = Just read_gc_work,
 
324
                                  gc_time    = Just read_gc,
 
325
                                  instrs     = Just (read is),
 
326
                                  mem_reads  = Just (read mem_rs),
 
327
                                  mem_writes = Just (read mem_ws),
 
328
                                  cache_misses = Just (read cache_misses),
 
329
                                  allocs     = Just (read allocs),
 
330
                                  run_status = Success })];
 
331
            Nothing ->
 
332
        
 
333
        case matchRegex wrong_output l of {
 
334
            Just ("stdout":_) -> 
 
335
                parse_run_time prog ls (combineRunResult WrongStdout ex);
 
336
            Just ("stderr":_) -> 
 
337
                parse_run_time prog ls (combineRunResult WrongStderr ex);
 
338
            Nothing ->
 
339
                        
 
340
        case matchRegex wrong_exit_status l of {
 
341
            Just (wanted:got:_) -> 
 
342
                parse_run_time prog ls (combineRunResult (Exit (read got)) ex);
 
343
            Nothing -> 
 
344
 
 
345
        case matchRegex out_of_heap l of {
 
346
            Just _ -> 
 
347
                parse_run_time prog ls (combineRunResult OutOfHeap ex);
 
348
            Nothing -> 
 
349
 
 
350
        case matchRegex out_of_stack l of {
 
351
            Just _ -> 
 
352
                parse_run_time prog ls (combineRunResult OutOfStack ex);
 
353
            Nothing -> 
 
354
                parse_run_time prog ls ex;
 
355
 
 
356
        }}}}}}}}
 
357
 
 
358
combineRunResult OutOfHeap  _           = OutOfHeap
 
359
combineRunResult _          OutOfHeap   = OutOfHeap
 
360
combineRunResult OutOfStack _           = OutOfStack
 
361
combineRunResult _          OutOfStack  = OutOfStack
 
362
combineRunResult (Exit e)   _           = Exit e
 
363
combineRunResult _          (Exit e)    = Exit e
 
364
combineRunResult exit       _            = exit
 
365
 
 
366
parse_size prog mod [] = []
 
367
parse_size prog mod (l:ls) =
 
368
        case matchRegex size_re l of
 
369
            Nothing -> parse_size prog mod ls
 
370
            Just (text:datas:bss:_) 
 
371
                 | prog == mod ->
 
372
                        [(prog,emptyResults{binary_size = 
 
373
                                              Just (read text + read datas),
 
374
                                    compile_status = Success})]
 
375
                 | otherwise ->
 
376
                        let ms  = addToFM emptyFM mod (read text + read datas)
 
377
                        in
 
378
                        [(prog,emptyResults{module_size = ms})]
 
379