Thu Dec 21 12:55:36 CET 2006 Alexey Rodriguez <mrchebas@gmail.com>
* Ability to read counter stats
diff -rN -u old-ghc/utils/nofib-analyse/Main.hs new-ghc/utils/nofib-analyse/Main.hs
|
old
|
new
|
|
| 119 | 119 | mreads_spec = SpecP "Memory Reads" "Reads" "mem-reads" mem_reads run_status always_ok |
| 120 | 120 | mwrite_spec = SpecP "Memory Writes" "Writes" "mem-writes" mem_writes run_status always_ok |
| 121 | 121 | cmiss_spec = SpecP "Cache Misses" "Misses" "cache-misses" cache_misses run_status always_ok |
| | 122 | cpu_counter_spec counter extract = SpecP counter counter counter (mean extract) run_status always_ok |
| | 123 | |
| | 124 | mk_cpu_counter_specs rs wantGC = map (uncurry cpu_counter_spec) countersAndSelectors |
| | 125 | where |
| | 126 | predWantGC ('G':'C':_,_) = wantGC |
| | 127 | predWantGC _ = not wantGC |
| | 128 | -- We retain the counters we're interested in |
| | 129 | countersAndSelectors = filter predWantGC (zip counters selectors) |
| | 130 | -- Counter names obtained from a nofib run |
| | 131 | counters = map fst . |
| | 132 | get_counters . |
| | 133 | cpu_counters . |
| | 134 | head . |
| | 135 | Map.elems . |
| | 136 | head $ rs -- Are there CPU counters there? |
| | 137 | -- How to access counter data |
| | 138 | selectors = [ selIth i . get_counters . cpu_counters | i<-[0..] ] |
| | 139 | selIth i ls | length ls <= i = [] |
| | 140 | | otherwise = snd (ls !! i) |
| 122 | 141 | |
| 123 | 142 | all_specs = [ |
| 124 | 143 | size_spec, |
| … |
… |
|
| 381 | 400 | . (if (length results == 2) |
| 382 | 401 | then ascii_summary_table False results summary_spec summary_rows . str "\n\n" |
| 383 | 402 | else id) |
| 384 | | . interleave "\n\n" (map (asciiGenProgTable results args) per_prog_result_tab) |
| | 403 | . interleave "\n\n" (map (asciiGenProgTable results args) (counters_specs ++ per_prog_result_tab)) |
| 385 | 404 | . str "\n" |
| 386 | 405 | . interleave "\n\n" (map (asciiGenModTable results args) per_module_result_tab) |
| 387 | 406 | ) "\n" |
| | 407 | where |
| | 408 | -- Report specifications for counters |
| | 409 | counters_specs = mk_cpu_counter_specs results False ++ |
| | 410 | mk_cpu_counter_specs results True |
| 388 | 411 | |
| 389 | 412 | asciiGenProgTable results args (SpecP title _ anc get_result get_status result_ok) |
| 390 | 413 | = str title |
| … |
… |
|
| 756 | 779 | |
| 757 | 780 | interleave s = foldr1 (\a b -> a . str s . b) |
| 758 | 781 | |
| 759 | | fIELD_WIDTH = 16 :: Int |
| | 782 | fIELD_WIDTH = 25 :: Int |
| 760 | 783 | |
| 761 | 784 | ----------------------------------------------------------------------------- |
diff -rN -u old-ghc/utils/nofib-analyse/Slurp.hs new-ghc/utils/nofib-analyse/Slurp.hs
|
old
|
new
|
|
| 4 | 4 | -- |
| 5 | 5 | ----------------------------------------------------------------------------- |
| 6 | 6 | |
| 7 | | module Slurp (Status(..), Results(..), ResultTable, parse_log) where |
| | 7 | module Slurp (Status(..), Results(..), ResultTable, parse_log, get_counters, CpuCounters) where |
| 8 | 8 | |
| 9 | 9 | import CmdLine |
| 10 | 10 | |
| … |
… |
|
| 27 | 27 | | Exit Int |
| 28 | 28 | | WrongStdout |
| 29 | 29 | | WrongStderr |
| | 30 | deriving Show |
| 30 | 31 | |
| 31 | 32 | data Results = Results { |
| 32 | 33 | compile_time :: Map String Float, |
| … |
… |
|
| 43 | 44 | gc_time :: [Float], |
| 44 | 45 | allocs :: Maybe Integer, |
| 45 | 46 | run_status :: Status, |
| 46 | | compile_status :: Status |
| 47 | | } |
| | 47 | compile_status :: Status, |
| | 48 | cpu_counters :: CpuCounters |
| | 49 | } deriving Show |
| | 50 | |
| | 51 | data CpuCounters |
| | 52 | = CpuCCalculated [(String,[Float])] -- Probably horribly inneficient but somehow flexible. |
| | 53 | | CpuCEmpty |
| | 54 | | CpuCError -- Inconsistent counters, probably ran with different counter options, so we ignore it. |
| | 55 | deriving Show |
| 48 | 56 | |
| 49 | 57 | emptyResults = Results { |
| 50 | 58 | compile_time = Map.empty, |
| … |
… |
|
| 61 | 69 | gc_work = Nothing, |
| 62 | 70 | allocs = Nothing, |
| 63 | 71 | compile_status = NotDone, |
| 64 | | run_status = NotDone |
| | 72 | run_status = NotDone, |
| | 73 | cpu_counters = CpuCEmpty |
| 65 | 74 | } |
| 66 | 75 | |
| 67 | 76 | ----------------------------------------------------------------------------- |
| … |
… |
|
| 104 | 113 | ghc3_re = GHC 4.03 (includes "xxxx bytes GC work") |
| 105 | 114 | -} |
| 106 | 115 | |
| 107 | | 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>>" |
| | 116 | 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>>" |
| 108 | 117 | |
| 109 | | 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>>" |
| | 118 | 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>>" |
| 110 | 119 | |
| 111 | | 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>>" |
| | 120 | 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>>" |
| 112 | 121 | |
| 113 | 122 | 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>>" |
| 114 | 123 | |
| … |
… |
|
| 143 | 152 | cache_misses = cm1, |
| 144 | 153 | gc_time = gt1, gc_work = gw1, |
| 145 | 154 | binary_size = bs1, allocs = al1, |
| 146 | | run_status = rs1, compile_status = cs1 } |
| | 155 | run_status = rs1, compile_status = cs1 , |
| | 156 | cpu_counters = cpuc1 } |
| 147 | 157 | Results{ compile_time = ct2, link_time = lt2, |
| 148 | 158 | module_size = ms2, |
| 149 | 159 | run_time = rt2, mut_time = mt2, |
| … |
… |
|
| 151 | 161 | cache_misses = cm2, |
| 152 | 162 | gc_time = gt2, gc_work = gw2, |
| 153 | 163 | binary_size = bs2, allocs = al2, |
| 154 | | run_status = rs2, compile_status = cs2 } |
| | 164 | run_status = rs2, compile_status = cs2 , |
| | 165 | cpu_counters = cpuc2 } |
| 155 | 166 | = Results{ compile_time = Map.unionWith (flip const) ct1 ct2, |
| 156 | 167 | module_size = Map.unionWith (flip const) ms1 ms2, |
| 157 | 168 | link_time = combMaybes lt1 lt2, |
| … |
… |
|
| 166 | 177 | binary_size = combMaybes bs1 bs2, |
| 167 | 178 | allocs = combMaybes al1 al2, |
| 168 | 179 | run_status = combStatus rs1 rs2, |
| 169 | | compile_status = combStatus cs1 cs2 } |
| | 180 | compile_status = combStatus cs1 cs2, |
| | 181 | cpu_counters = combCpuCounters cpuc1 cpuc2 } |
| 170 | 182 | |
| 171 | 183 | combMaybes m1 m2 = case maybeToList m1 ++ maybeToList m2 of |
| 172 | 184 | [] -> Nothing |
| 173 | 185 | (x:_) -> Just x |
| 174 | 186 | |
| | 187 | combCpuCounters :: CpuCounters -> CpuCounters -> CpuCounters |
| | 188 | combCpuCounters CpuCError _ = CpuCError |
| | 189 | combCpuCounters _ CpuCError = CpuCError |
| | 190 | combCpuCounters CpuCEmpty c = c |
| | 191 | combCpuCounters c CpuCEmpty = c |
| | 192 | combCpuCounters (CpuCCalculated cs1) (CpuCCalculated cs2) |
| | 193 | = foldr mergeCounter (CpuCCalculated []) $ zip cs1 cs2 |
| | 194 | where |
| | 195 | mergeCounter ((n1,ss1),(n2,ss2)) (CpuCCalculated ls) |
| | 196 | | n1 == n2 = CpuCCalculated ((n1,ss1++ss2) : ls) |
| | 197 | mergeCounter _ CpuCError = CpuCError |
| | 198 | |
| | 199 | get_counters CpuCError = [] |
| | 200 | get_counters CpuCEmpty = [] |
| | 201 | get_counters (CpuCCalculated ls) = ls |
| | 202 | |
| | 203 | |
| 175 | 204 | combStatus NotDone x = x |
| 176 | 205 | combStatus x NotDone = x |
| 177 | 206 | combStatus x y = x |
| … |
… |
|
| 278 | 307 | parse_run_time prog [] res ex = [(prog, res{run_status=ex})] |
| 279 | 308 | parse_run_time prog (l:ls) res ex = |
| 280 | 309 | case matchRegex ghc1_re l of { |
| 281 | | Just (allocs:_:_:_:_:init:_:mut:_:gc:_) -> |
| | 310 | Just (allocs:_:_:_:_:init:_:mut:_:gc:_:cpu:_) -> |
| 282 | 311 | got_run_result allocs init mut gc Nothing |
| 283 | | Nothing Nothing Nothing Nothing; |
| | 312 | Nothing Nothing Nothing Nothing (mk_counter cpu); |
| 284 | 313 | Nothing -> |
| 285 | 314 | |
| 286 | 315 | case matchRegex ghc2_re l of { |
| 287 | | Just (allocs:_:_:_:_:_:init:_:mut:_:gc:_) -> |
| | 316 | Just (allocs:_:_:_:_:_:init:_:mut:_:gc:_:cpu:_) -> |
| 288 | 317 | got_run_result allocs init mut gc Nothing |
| 289 | | Nothing Nothing Nothing Nothing; |
| | 318 | Nothing Nothing Nothing Nothing (mk_counter cpu); |
| 290 | 319 | |
| 291 | 320 | Nothing -> |
| 292 | 321 | |
| 293 | 322 | case matchRegex ghc3_re l of { |
| 294 | | Just (allocs:_:_:_:_:gc_work:_:init:_:mut:_:gc:_) -> |
| | 323 | Just (allocs:_:_:_:_:gc_work:_:init:_:mut:_:gc:_:cpu:_) -> |
| 295 | 324 | got_run_result allocs init mut gc (Just (read gc_work)) |
| 296 | | Nothing Nothing Nothing Nothing; |
| | 325 | Nothing Nothing Nothing Nothing (mk_counter cpu); |
| 297 | 326 | |
| 298 | 327 | Nothing -> |
| 299 | 328 | |
| … |
… |
|
| 301 | 330 | Just (allocs:_:_:_:_:gc_work:_:init:_:mut:_:gc:_:is:mem_rs:mem_ws:cache_misses:_) -> |
| 302 | 331 | got_run_result allocs init mut gc (Just (read gc_work)) |
| 303 | 332 | (Just (read is)) (Just (read mem_rs)) |
| 304 | | (Just (read mem_ws)) (Just (read cache_misses)); |
| | 333 | (Just (read mem_ws)) (Just (read cache_misses)) CpuCEmpty; |
| 305 | 334 | |
| 306 | 335 | Nothing -> |
| 307 | 336 | |
| … |
… |
|
| 330 | 359 | |
| 331 | 360 | }}}}}}}} |
| 332 | 361 | where |
| 333 | | got_run_result allocs init mut gc gc_work instrs mem_rs mem_ws cache_misses |
| | 362 | mk_counter "" = CpuCEmpty -- Assumming that a non-matching '?' regexp returns empty |
| | 363 | mk_counter s = CpuCCalculated (read s) |
| | 364 | got_run_result allocs init mut gc gc_work instrs mem_rs mem_ws cache_misses counters |
| 334 | 365 | = -- trace ("got_run_result: " ++ init ++ ", " ++ mut ++ ", " ++ gc) $ |
| 335 | 366 | let |
| 336 | 367 | read_mut = read mut |
| … |
… |
|
| 346 | 377 | mem_reads = mem_rs, |
| 347 | 378 | mem_writes = mem_ws, |
| 348 | 379 | cache_misses = cache_misses, |
| 349 | | run_status = Success |
| | 380 | run_status = Success, |
| | 381 | cpu_counters = counters |
| 350 | 382 | } |
| 351 | 383 | in |
| 352 | 384 | parse_run_time prog ls res' Success |