examples: annotate examples
[nit.git] / lib / performance_analysis.nit
1 # This file is part of NIT (http://www.nitlanguage.org).
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 # Services to gather information on the performance of events by categories
16 #
17 # Provides `PerfMap` to manage all the categories and
18 # `PerfEntry` for per-category statistics.
19 #
20 # ~~~
21 # for i in 100.times do
22 # var clock = new Clock
23 #
24 # # Do some "work" here
25 # nanosleep(0, 1000000)
26 #
27 # # Register the perf
28 # sys.perfs["sleep 1ms"].add clock.lapse
29 #
30 # # Do some other "work" here
31 # nanosleep(0, 5000000)
32 #
33 # # Register the perf
34 # sys.perfs["sleep 5ms"].add clock.lapse
35 # end
36 #
37 # assert sys.perfs["sleep 1ms"].count == 100
38 # assert sys.perfs["sleep 1ms"].avg.is_approx(0.001, 0.001)
39 # assert sys.perfs["sleep 5ms"].avg.is_approx(0.005, 0.005)
40 # ~~~
41 module performance_analysis
42
43 import realtime
44
45 redef class Sys
46 # Main `PerfMap` available by default
47 var perfs = new PerfMap
48 end
49
50 # Collection of statistics on many events
51 class PerfMap
52 super HashMap[String, PerfEntry]
53
54 redef fun provide_default_value(key)
55 do
56 if not key isa String then return super
57
58 var ts = new PerfEntry(key)
59 self[key] = ts
60 return ts
61 end
62
63 redef fun to_s
64 do
65 var prec = 3
66
67 var table = new Map[String, Array[String]]
68 for event, stats in self do
69 table[event] = [event,
70 stats.min.to_precision(prec),
71 stats.max.to_precision(prec),
72 stats.avg.to_precision(prec),
73 stats.sum.to_precision(prec),
74 stats.count.to_s]
75 end
76
77 var widths = [0] * 6
78 for event, row in table do
79 for i in row.length.times do
80 widths[i] = widths[i].max(row[i].length)
81 end
82 end
83
84 var s = "# {"Event".justify(widths[0], 0.0)} {"min".justify(widths[1], 0.5)} {"max".justify(widths[2], 0.5)} {"avg".justify(widths[3], 0.5)} {"sum".justify(widths[4], 0.5)} {"count".justify(widths[5], 0.5)}\n"
85
86 var sorted_events = table.keys.to_a
87 alpha_comparator.sort sorted_events
88 for event in sorted_events do
89 var row = table[event]
90 s += "*"
91 for c in row.length.times do
92 var cell = row[c]
93 s += " "
94 if c == 0 then
95 s += cell.justify(widths[c], 0.0, '.')
96 else s += cell.justify(widths[c], 1.0)
97 end
98 s += "\n"
99 end
100 return s
101 end
102 end
103
104 # Statistics on wall clock execution time of a category of events by `name`
105 class PerfEntry
106
107 # Name of the category
108 var name: String
109
110 # Shortest execution time of registered events
111 var min = 0.0
112
113 # Longest execution time of registered events
114 var max = 0.0
115
116 # Average execution time of registered events
117 var avg = 0.0
118
119 # Number of registered events
120 var count = 0
121
122 # Total execution time of this event
123 var sum = 0.0
124
125 # Register a new event execution time in seconds
126 fun add(time: Float)
127 do
128 if time.to_f < min.to_f or count == 0 then min = time
129 if time.to_f > max.to_f then max = time
130
131 sum += time
132 count += 1
133 avg = sum / count.to_f
134 end
135
136 redef fun to_s do return "min {min}, max {max}, avg {avg}, sum {sum}, count {count}"
137 end