-
Notifications
You must be signed in to change notification settings - Fork 2
/
Timer.mag
222 lines (190 loc) · 6.15 KB
/
Timer.mag
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
declare type PGGTimer;
declare type PGGTimerStack: PGGTimer;
declare attributes PGGTimerStack: current_label;
declare type PGGTimerBase: PGGTimerStack;
declare attributes PGGTimerBase: last_time, times, counts, labels, idxs;
declare type PGGTimerFork: PGGTimerStack;
declare attributes PGGTimerFork: parent, parent_label;
declare type PGGTimerNull: PGGTimer;
declare verbose PGG_Timer, 2;
intrinsic PGG_Timer() -> PGGTimerBase
{A new timer.}
t := New(PGGTimerBase);
t`last_time := Cputime();
t`times := [RealField()|];
t`counts := [Integers()|];
t`labels := [PowerSequence(Strings())|];
t`current_label := [Strings()|];
t`idxs := AssociativeArray(PowerSequence(Strings()));
return t;
end intrinsic;
NULL := New(PGGTimerNull);
intrinsic PGG_NullTimer() -> PGGTimerNull
{The null timer.}
return NULL;
end intrinsic;
intrinsic Fork(t :: PGGTimerStack) -> PGGTimerFork
{Forks t.}
t2 := New(PGGTimerFork);
t2`parent := t;
t2`parent_label := t`current_label;
t2`current_label := [Strings()|];
return t2;
end intrinsic;
intrinsic Fork(t :: PGGTimerNull) -> PGGTimerNull
{"}
return NULL;
end intrinsic;
intrinsic FindIndex(t :: PGGTimerBase, label :: [MonStgElt]) -> RngIntElt
{The index of the given label. If it doesn't exist, creates it first.}
ok, i := IsDefined(t`idxs, label);
if ok then
return i;
end if;
Append(~t`times, 0);
Append(~t`counts, 0);
Append(~t`labels, label);
t`idxs[label] := #t`labels;
return #t`labels;
end intrinsic;
intrinsic Update(t :: PGGTimerBase, c :: RngIntElt, label :: [MonStgElt])
{Assigns the accumulated time to the given label.}
now := Cputime();
ok, i := IsDefined(t`idxs, label);
if not ok then
Append(~t`times, 0);
Append(~t`counts, 0);
Append(~t`labels, label);
t`idxs[label] := #t`labels;
i := #t`labels;
end if;
t`times[i] +:= now - t`last_time;
t`counts[i] +:= c;
t`last_time := now;
vprint PGG_Timer: "PGG_Timer", label, c, now;
end intrinsic;
intrinsic Update(t :: PGGTimerFork, c :: RngIntElt, label :: [MonStgElt])
{"}
Update(t`parent, c, t`parent_label cat label);
end intrinsic;
intrinsic Update(t :: PGGTimerNull, c :: RngIntElt, label :: [MonStgElt])
{"}
return;
end intrinsic;
intrinsic Update(t :: PGGTimer, label :: [MonStgElt])
{"}
Update(t, 0, label);
end intrinsic;
intrinsic GetLabel(t :: PGGTimer) -> []
{Gets the current label.}
return t`current_label;
end intrinsic;
intrinsic SetLabel(t :: PGGTimer, label :: [MonStgElt])
{Sets the label.}
Update(t, t`current_label);
t`current_label := label;
end intrinsic;
intrinsic Push(t :: PGGTimerBase, x :: MonStgElt)
{Assings time to the current label, then appends x to the label.}
Update(t, t`current_label);
Append(~t`current_label, x);
end intrinsic;
intrinsic Push(t :: PGGTimerNull, x :: MonStgElt)
{"}
return;
end intrinsic;
intrinsic Pop(t :: PGGTimerStack, n :: RngIntElt)
{Assigns time to the current label, then pops n items from the label.}
error if #t`current_label lt n, "n greater than label length";
Update(t, 1, t`current_label);
t`current_label := t`current_label[1..#t`current_label-n];
end intrinsic;
intrinsic Pop(t :: PGGTimerNull, n :: RngIntElt)
{"}
return;
end intrinsic;
intrinsic Pop(t :: PGGTimerStack, n :: RngIntElt, x :: MonStgElt)
{Assigns time to the current label, then pops n items from the label, the nth being x.}
error if #t`current_label lt n, "n greater than label length";
error if t`current_label[#t`current_label-n+1] ne x, "incorrect label entry";
Update(t, 1, t`current_label);
t`current_label := t`current_label[1..#t`current_label-n];
end intrinsic;
intrinsic Pop(t :: PGGTimerNull, n :: RngIntElt, x :: MonStgElt)
{"}
return;
end intrinsic;
intrinsic Pop(t :: PGGTimer, x :: MonStgElt)
{Assigns time to the current label, then pops the last item from the label, which must be x.}
Pop(t, 1, x);
end intrinsic;
intrinsic Pop(t :: PGGTimer)
{Assigns time to the current label, then pops the last item from the label.}
Pop(t, 1);
end intrinsic;
intrinsic Swap(t :: PGGTimerStack, x :: MonStgElt)
{Assigns time to the current label, then swaps the last item from the label to x.}
error if #t`current_label lt 1, "label too short";
Update(t, 1, t`current_label);
t`current_label[#t`current_label] := x;
end intrinsic;
intrinsic Swap(t :: PGGTimerNull, x :: MonStgElt)
{"}
return;
end intrinsic;
intrinsic Log(t :: PGGTimerStack, x :: MonStgElt)
{Assigns time to the current label with x appended.}
Update(t, 1, Append(t`current_label, x));
end intrinsic;
intrinsic Log(t :: PGGTimerNull, x :: MonStgElt)
{"}
return;
end intrinsic;
intrinsic Tree(t :: PGGTimerBase : Total:="TOTAL", Other:="OTHER") -> Tup
{A tree representation of t.}
procedure insert(~node, label, tm, ct)
node[2] +:= tm;
if #label gt 0 then
for i in [1..#node[4]] do
if node[4][i][1] eq label[1] then
insert(~node[4][i], label[2..#label], tm, ct);
return;
end if;
end for;
Append(~node[4], <label[1], 0.0, 0, [**]>);
insert(~node[4][#node[4]], label[2..#label], tm, ct);
else
node[3] +:= ct;
end if;
end procedure;
procedure rest(~node)
if #node[4] gt 0 then
Append(~node[4], <Other, node[2] - &+[n[2] : n in node[4]], 0, [**]>);
for i in [1..#node[4]] do
rest(~node[4][i]);
end for;
end if;
end procedure;
root := <Total, 0.0, 0, [**]>;
for i in [1..#t`labels] do
insert(~root, t`labels[i], t`times[i], t`counts[i]);
end for;
rest(~root);
return root;
end intrinsic;
intrinsic PrintTree(t :: PGGTimer)
{Prints t as a tree.}
procedure pr(node, depth)
if node[3] ge 1 or node[2] ge 0.01 then
printf "%o%6.2o", &cat[Strings() | " " : i in [1..depth]], node[2];
if node[3] ne 0 then
printf " (%o)", node[3];
end if;
printf " %o\n", node[1];
for n in node[4] do
pr(n, depth+1);
end for;
end if;
end procedure;
pr(Tree(t), 0);
end intrinsic;