SCM Repository
Annotation of /sml/trunk/src/compiler/FLINT/clos/allocprof.sml
Parent Directory
|
Revision Log
Revision 93 -
(view)
(download)
Original Path: sml/branches/SMLNJ/src/compiler/FLINT/clos/allocprof.sml
1 : | monnier | 16 | (* Copyright 1996 by Bell Laboratories *) |
2 : | (* allocprof.sml *) | ||
3 : | |||
4 : | structure AllocProf = | ||
5 : | struct | ||
6 : | |||
7 : | local open CPS | ||
8 : | |||
9 : | structure CGoptions = Control.CG | ||
10 : | structure P = CPS.P (* to avoid confusing SourceGroup *) | ||
11 : | val mkLvar = LambdaVar.mkLvar | ||
12 : | |||
13 : | val ARRAYS = 0 | ||
14 : | val ARRAYSIZE = 1 | ||
15 : | val STRINGS = 2 | ||
16 : | val STRINGSIZE = 3 | ||
17 : | val REFCELLS = 4 | ||
18 : | val REFLISTS = 5 | ||
19 : | val CLOSURES = 6 | ||
20 : | val CLOSURESLOTS = 11 | ||
21 : | val CLOSUREOVFL = (CLOSURES + CLOSURESLOTS) | ||
22 : | val KCLOSURES = (CLOSUREOVFL + 1) | ||
23 : | val KCLOSURESLOTS = 11 | ||
24 : | val KCLOSUREOVFL = (KCLOSURES + KCLOSURESLOTS) | ||
25 : | val CCLOSURES = (KCLOSUREOVFL + 1) | ||
26 : | val CCLOSURESLOTS = 11 | ||
27 : | val CCLOSUREOVFL = (CCLOSURES + CCLOSURESLOTS) | ||
28 : | val LINKS = (CCLOSUREOVFL + 1) | ||
29 : | val LINKSLOTS = 11 | ||
30 : | val LINKOVFL = (LINKS + LINKSLOTS) | ||
31 : | val SPLINKS = (LINKOVFL + 1) | ||
32 : | val SPLINKSLOTS = 11 | ||
33 : | val SPLINKOVFL = (SPLINKS + SPLINKSLOTS) | ||
34 : | val RECORDS = (SPLINKOVFL + 1) | ||
35 : | val RECORDSLOTS = 11 | ||
36 : | val RECORDOVFL = (RECORDS + RECORDSLOTS) | ||
37 : | val SPILLS = (RECORDOVFL + 1) | ||
38 : | val SPILLSLOTS = 21 | ||
39 : | val SPILLOVFL = (SPILLS + SPILLSLOTS) | ||
40 : | val KNOWNCALLS = (SPILLOVFL + 1) | ||
41 : | val STDKCALLS = (KNOWNCALLS + 1) | ||
42 : | val STDCALLS = (STDKCALLS + 1) | ||
43 : | val CNTCALLS = (STDCALLS + 1) | ||
44 : | val CNTKCALLS = (CNTCALLS + 1) | ||
45 : | val CSCNTCALLS = (CNTKCALLS + 1) | ||
46 : | val CSCNTKCALLS = (CSCNTCALLS + 1) | ||
47 : | val TLIMITCHECK = (CSCNTKCALLS+1) | ||
48 : | val ALIMITCHECK = (TLIMITCHECK+1) | ||
49 : | val ARITHOVH = (ALIMITCHECK+1) | ||
50 : | val ARITHSLOTS = 5 | ||
51 : | (* Make sure the array assigned to varptr in the runtime system is at | ||
52 : | least this big!! Test how big by doing an allocReset from batch. *) | ||
53 : | val PROFSIZE = (ARITHOVH+ARITHSLOTS) | ||
54 : | |||
55 : | val PROFREG = 0 (* use pseudo register 0 *) | ||
56 : | |||
57 : | in | ||
58 : | |||
59 : | local | ||
60 : | fun prof(s,i) = (* Header to increment slot s by i *) | ||
61 : | (fn ce => let val a1 = mkLvar() and a2 = mkLvar() | ||
62 : | and x = mkLvar() and n = mkLvar() | ||
63 : | in LOOKER(P.getpseudo,[INT PROFREG],a1,BOGt, | ||
64 : | LOOKER(P.subscript,[VAR a1,INT s],x,INTt, | ||
65 : | ARITH(P.iadd,[VAR x,INT i],n,INTt, | ||
66 : | LOOKER(P.getpseudo,[INT PROFREG],a2,BOGt, | ||
67 : | SETTER(P.unboxedupdate,[VAR a2,INT s,VAR n],ce))))) | ||
68 : | end) | ||
69 : | |||
70 : | fun profSlots(base,slots,ovfl) cost = | ||
71 : | if cost < slots | ||
72 : | then prof(base+cost,1) | ||
73 : | else prof(base,1) o prof(ovfl,cost) | ||
74 : | |||
75 : | val id = (fn x => x) | ||
76 : | in | ||
77 : | |||
78 : | local val profLinks0 = profSlots(LINKS,LINKSLOTS,LINKOVFL) | ||
79 : | in | ||
80 : | fun profLinks(cost) = if cost=0 then id else profLinks0 cost | ||
81 : | end | ||
82 : | |||
83 : | fun profRecLinks(l) = foldr (fn (cost,h) => profLinks(cost) o h) id l | ||
84 : | |||
85 : | local val profRecord0 = profSlots(RECORDS,RECORDSLOTS,RECORDOVFL) | ||
86 : | in | ||
87 : | fun profRecord(cost) = if cost=0 then id else profRecord0 cost | ||
88 : | end | ||
89 : | |||
90 : | val profClosure = profSlots(CLOSURES,CLOSURESLOTS,CLOSUREOVFL) | ||
91 : | |||
92 : | val profKClosure = profSlots(KCLOSURES,KCLOSURESLOTS,KCLOSUREOVFL) | ||
93 : | |||
94 : | val profCClosure = profSlots(CCLOSURES,CCLOSURESLOTS,CCLOSUREOVFL) | ||
95 : | |||
96 : | val profSpill = profSlots(SPILLS,SPILLSLOTS,SPILLOVFL) | ||
97 : | |||
98 : | val profStdCall = prof(STDCALLS,1) | ||
99 : | |||
100 : | val profStdkCall = prof(STDKCALLS,1) | ||
101 : | |||
102 : | val profCntCall = prof(CNTCALLS,1) | ||
103 : | |||
104 : | val profCntkCall = prof(CNTKCALLS,1) | ||
105 : | |||
106 : | val profCSCntCall = prof(CSCNTCALLS,1) | ||
107 : | |||
108 : | val profCSCntkCall = prof(CSCNTKCALLS,1) | ||
109 : | |||
110 : | val profKnownCall = prof(KNOWNCALLS,1) | ||
111 : | |||
112 : | fun profRefCell k = prof(REFCELLS,k) | ||
113 : | |||
114 : | val profRefList = prof(REFLISTS,1) | ||
115 : | |||
116 : | val profTLCHECK = prof(TLIMITCHECK,1) | ||
117 : | |||
118 : | val profALCHECK = prof(ALIMITCHECK,1) | ||
119 : | |||
120 : | end (* local *) | ||
121 : | |||
122 : | |||
123 : | fun print_profile_info(outstrm) = | ||
124 : | let val im = Int.toString | ||
125 : | fun pr x = TextIO.output(outstrm,x) | ||
126 : | val printf = app pr | ||
127 : | (* Right justify st in a string of length w. *) | ||
128 : | fun field (st,w) = | ||
129 : | if w <= String.size st then st | ||
130 : | else let val s = " " ^ st | ||
131 : | in substring(s,String.size s - w, w) | ||
132 : | end | ||
133 : | |||
134 : | fun ifield(i,w) = field(im i,w) | ||
135 : | (* Put a decimal point at position w in string st. *) | ||
136 : | fun decimal(st,w) = | ||
137 : | let val l = String.size st - w | ||
138 : | val a = if (l <= 0) then "0" else substring(st,0,l) | ||
139 : | val st' = "0000000000" ^ st | ||
140 : | in a ^ "." ^ substring(st',String.size st' - w,w) | ||
141 : | end | ||
142 : | fun muldiv(i,j,k) = | ||
143 : | (i*j div k) handle Overflow => muldiv(i,j div 2, k div 2) | ||
144 : | fun decfield(n,j,k,w1,w2) = | ||
145 : | field(decimal(im (muldiv(n,j,k)),w1) | ||
146 : | handle Div => "",w2) | ||
147 : | (* Returns the percentage i/j to 1 decimal place in a field of width k *) | ||
148 : | fun percent(i,j,k) = decfield(1000,i,j,1,k) | ||
149 : | (* Returns the percentage i/j to 2 decimal places in a field of width k*) | ||
150 : | fun percent2(i,j,k) = decfield(10000,i,j,2,k) | ||
151 : | |||
152 : | fun for(start,upto,f) = | ||
153 : | let fun iter(i,cum:int) = | ||
154 : | if i < upto then iter(i+1,cum + f(i)) else cum | ||
155 : | in iter(start,0) | ||
156 : | end | ||
157 : | fun for'(start,upto,f) = | ||
158 : | let fun iter(i) = if i < upto then (f(i); iter(i+1)) else () | ||
159 : | in iter(start) | ||
160 : | end | ||
161 : | |||
162 : | |||
163 : | val profvec : int array = Unsafe.getPseudo(PROFREG) | ||
164 : | fun getprof(x) = Array.sub(profvec,x) | ||
165 : | fun links(i) = getprof(LINKS+i) | ||
166 : | fun closures(i) = getprof(CLOSURES+i) | ||
167 : | fun kclosures(i) = getprof(KCLOSURES+i) | ||
168 : | fun cclosures(i) = getprof(CCLOSURES+i) | ||
169 : | fun records(i) = getprof(RECORDS+i) | ||
170 : | fun spills(i) = getprof(SPILLS+i) | ||
171 : | |||
172 : | val num_calls = getprof(KNOWNCALLS) | ||
173 : | + getprof(STDKCALLS) + getprof(STDCALLS) | ||
174 : | + getprof(CNTKCALLS) + getprof(CNTCALLS) | ||
175 : | + getprof(CSCNTKCALLS) + getprof(CSCNTCALLS) | ||
176 : | |||
177 : | val num_closures = for(0, CLOSURESLOTS,fn i => closures(i)) | ||
178 : | val space_closures = for(1, CLOSURESLOTS, fn i => closures(i) * (i+1)) | ||
179 : | val space_closures = space_closures + getprof(CLOSUREOVFL) + closures(0) | ||
180 : | |||
181 : | val num_kclosures = for(0, KCLOSURESLOTS,fn i => kclosures(i)) | ||
182 : | val space_kclosures = for(1, KCLOSURESLOTS, fn i => kclosures(i) * (i+1)) | ||
183 : | val space_kclosures = | ||
184 : | space_kclosures + getprof(KCLOSUREOVFL) + kclosures(0) | ||
185 : | |||
186 : | val num_cclosures = for(0, CCLOSURESLOTS,fn i => cclosures(i)) | ||
187 : | val space_cclosures = for(1, CCLOSURESLOTS, fn i => cclosures(i) * (i+1)) | ||
188 : | val space_cclosures = | ||
189 : | space_cclosures + getprof(CCLOSUREOVFL) + cclosures(0) | ||
190 : | |||
191 : | val num_closure_accesses = for(0, LINKSLOTS, fn i => links(i)) | ||
192 : | val num_links_traced = for(1, LINKSLOTS, fn i => links(i) * i) | ||
193 : | val num_links_traced = num_links_traced + getprof(LINKOVFL) | ||
194 : | |||
195 : | val num_records = for(0, RECORDSLOTS, fn i => records(i)) | ||
196 : | val space_records = for(1, RECORDSLOTS, fn i => records(i) * (i+1)) | ||
197 : | val space_records = space_records + getprof(RECORDOVFL) + records(0) | ||
198 : | |||
199 : | val num_spills = for(0, SPILLSLOTS, fn i => spills(i)) | ||
200 : | val space_spills = for(1, SPILLSLOTS, fn i => spills(i) * (i+1)) | ||
201 : | val space_spills = space_spills + getprof(SPILLOVFL) + spills(0) | ||
202 : | val total = space_closures + space_kclosures + space_cclosures | ||
203 : | + space_records + space_spills | ||
204 : | + getprof(ARRAYSIZE) + getprof(ARRAYS) | ||
205 : | + getprof(STRINGSIZE) + getprof(STRINGS) | ||
206 : | + getprof(REFCELLS) * 2 | ||
207 : | + getprof(REFLISTS) * 2 | ||
208 : | |||
209 : | val descriptors = num_closures + num_kclosures + num_cclosures | ||
210 : | + num_records + num_spills | ||
211 : | + getprof(ARRAYS) + getprof(STRINGS)+ getprof(REFCELLS) | ||
212 : | |||
213 : | val sgetprof = im o getprof | ||
214 : | |||
215 : | fun printLinks() = | ||
216 : | if num_closure_accesses>0 then | ||
217 : | (for'(1, LINKSLOTS, | ||
218 : | fn k => | ||
219 : | if links(k) > 0 then | ||
220 : | printf[ifield(k,4), | ||
221 : | ifield(links(k),13), | ||
222 : | percent(links(k),num_closure_accesses,12), | ||
223 : | "%", | ||
224 : | ifield(links(k) * k,12), | ||
225 : | percent(links(k) * k, num_links_traced, 9), | ||
226 : | "%\n"] | ||
227 : | else ()); | ||
228 : | if links(0) > 0 then | ||
229 : | printf[">", | ||
230 : | ifield(LINKSLOTS - 1,5), | ||
231 : | ifield(links(0),9), | ||
232 : | percent(links(0),num_closure_accesses,10), | ||
233 : | "%", | ||
234 : | ifield(getprof(LINKOVFL),13), | ||
235 : | percent(getprof(LINKOVFL),num_links_traced,10), | ||
236 : | "%\n"] | ||
237 : | else (); | ||
238 : | |||
239 : | printf[decfield(100,num_links_traced,num_closure_accesses,2,0), | ||
240 : | " links were traced per access on average.\n\n"] | ||
241 : | ) else printf["\n"] (* end function printLinks *) | ||
242 : | |||
243 : | fun print1(num,name,slots,getstat,ovfl,space) = | ||
244 : | if num>0 then | ||
245 : | (printf[name,":\n"]; | ||
246 : | for'(1, slots, | ||
247 : | fn k => | ||
248 : | if getstat(k) > 0 then | ||
249 : | printf[ifield(k,6), | ||
250 : | ifield(getstat(k),9), | ||
251 : | percent(getstat(k),num,9), | ||
252 : | "%", | ||
253 : | ifield(getstat(k) * (k+1),13), | ||
254 : | percent(getstat(k) * (k+1), total, 10), | ||
255 : | "%\n"] | ||
256 : | else ()); | ||
257 : | if getstat(0) > 0 then | ||
258 : | printf[">", | ||
259 : | ifield(slots - 1,5), | ||
260 : | ifield(getstat(0),9), | ||
261 : | percent(getstat(0),num,9), | ||
262 : | "%", | ||
263 : | ifield(getprof(ovfl)+getstat(0),13), | ||
264 : | percent(getprof(ovfl)+getstat(0),total,10), | ||
265 : | "%\n"] | ||
266 : | else (); | ||
267 : | |||
268 : | printf["total:", | ||
269 : | ifield(num,9), | ||
270 : | ifield(space,23), | ||
271 : | percent(space,total,10), | ||
272 : | "% Average size ", | ||
273 : | decfield(100,space-num,num,2,0), | ||
274 : | "\n\n"] | ||
275 : | ) else if (String.size(name) > 12) | ||
276 : | then printf[name,": 0\n\n"] | ||
277 : | else printf[name,": ", | ||
278 : | ifield(0,13 - String.size(name)),"\n\n"] | ||
279 : | (* end function print1 *) | ||
280 : | |||
281 : | fun print2(stat,size,name) = | ||
282 : | if getprof(stat) <> 0 then | ||
283 : | printf[name, | ||
284 : | ifield(getprof(stat),6), | ||
285 : | ifield(getprof(size) + getprof(stat), 23), | ||
286 : | percent(getprof(size) + getprof(stat),total,10), | ||
287 : | "% Average size ", | ||
288 : | decfield(100,getprof(size),getprof(stat),2,0), | ||
289 : | "\n"] | ||
290 : | else printf[name,ifield(0,6),"\n"] | ||
291 : | |||
292 : | fun print3(stat,name) = | ||
293 : | if getprof(stat) <> 0 then | ||
294 : | printf[name, | ||
295 : | ifield(getprof(stat),6), | ||
296 : | ifield(getprof(stat) * 2, 23), | ||
297 : | percent(getprof(stat) * 2,total,10), | ||
298 : | "%\n"] | ||
299 : | else printf[name,ifield(0,6),"\n"] | ||
300 : | |||
301 : | fun print4(stat,name) = | ||
302 : | if getprof(stat) <> 0 then | ||
303 : | printf[name, ifield(getprof(stat),10), "\n"] | ||
304 : | else printf[name,ifield(0,12),"\n"] | ||
305 : | |||
306 : | in pr "\n-------------------- ALLOCATION PROFILE --------------------\n\n"; | ||
307 : | |||
308 : | pr "\n ----- FUNCTION CALLS -----\n"; | ||
309 : | if (num_calls > 0) then | ||
310 : | printf["Known functions: ", | ||
311 : | ifield(getprof(KNOWNCALLS),10), | ||
312 : | " (", | ||
313 : | percent(getprof(KNOWNCALLS),num_calls,4), | ||
314 : | "%)\n", | ||
315 : | |||
316 : | "Escaping functions: ", | ||
317 : | ifield(getprof(STDCALLS),10), | ||
318 : | " (", | ||
319 : | percent(getprof(STDCALLS),num_calls,4), | ||
320 : | "%)\n", | ||
321 : | |||
322 : | |||
323 : | "Known escaping functions: ", | ||
324 : | ifield(getprof(STDKCALLS),10), | ||
325 : | " (", | ||
326 : | percent(getprof(STDKCALLS),num_calls,4), | ||
327 : | "%)\n", | ||
328 : | |||
329 : | "Continuations: ", | ||
330 : | ifield(getprof(CNTCALLS),10), | ||
331 : | " (", | ||
332 : | percent(getprof(CNTCALLS),num_calls,4), | ||
333 : | "%)\n", | ||
334 : | |||
335 : | "Known continuations: ", | ||
336 : | ifield(getprof(CNTKCALLS),10), | ||
337 : | " (", | ||
338 : | percent(getprof(CNTKCALLS),num_calls,4), | ||
339 : | "%)\n", | ||
340 : | |||
341 : | "Callee-save continuations: ", | ||
342 : | ifield(getprof(CSCNTCALLS),10), | ||
343 : | " (", | ||
344 : | percent(getprof(CSCNTCALLS),num_calls,4), | ||
345 : | "%)\n", | ||
346 : | |||
347 : | "Known callee-save continuations: ", | ||
348 : | ifield(getprof(CSCNTKCALLS),10), | ||
349 : | " (", | ||
350 : | percent(getprof(CSCNTKCALLS),num_calls,4), | ||
351 : | "%)\n"] | ||
352 : | else (); | ||
353 : | printf["\nTotal function calls: ", | ||
354 : | ifield(num_calls,10),"\n\n"]; | ||
355 : | |||
356 : | |||
357 : | pr "\n ----- CLOSURE ACCESSES -----\n"; | ||
358 : | printf["Closure elements were accessed ", | ||
359 : | im num_closure_accesses, | ||
360 : | " times through ", | ||
361 : | im num_links_traced, | ||
362 : | " links:\n", | ||
363 : | "Size Accesses % accesses Links % links\n"]; | ||
364 : | printLinks(); | ||
365 : | |||
366 : | pr "\n ----- HEAP ALLOCATIONS -----\n"; | ||
367 : | pr " (only total sizes include descriptors)\n\n"; | ||
368 : | printf["TOTAL size ", im total]; | ||
369 : | if (total > 0) then ( | ||
370 : | printf["; ", | ||
371 : | im descriptors, " descriptors accounted for ", | ||
372 : | percent(descriptors,total,0), "%.\n\n"]) | ||
373 : | else printf[".\n\n"]; | ||
374 : | |||
375 : | printf[" Size Number % total Total size % TOTAL\n\n"]; | ||
376 : | |||
377 : | print1(num_closures,"Closures for escaping functions", | ||
378 : | CLOSURESLOTS,closures,CLOSUREOVFL,space_closures); | ||
379 : | print1(num_kclosures,"Closures for known functions", | ||
380 : | KCLOSURESLOTS,kclosures,KCLOSUREOVFL,space_kclosures); | ||
381 : | print1(num_cclosures,"Closures for callee-save continuations", | ||
382 : | CCLOSURESLOTS,cclosures,CCLOSUREOVFL,space_cclosures); | ||
383 : | |||
384 : | print1(num_records,"Records",RECORDSLOTS,records, | ||
385 : | RECORDOVFL,space_records); | ||
386 : | print1(num_spills,"Spills",SPILLSLOTS,spills, | ||
387 : | SPILLOVFL,space_spills); | ||
388 : | |||
389 : | print2(ARRAYS,ARRAYSIZE,"Arrays: "); | ||
390 : | print2(STRINGS,STRINGSIZE,"Strings: "); | ||
391 : | |||
392 : | print3(REFCELLS,"Refs: "); | ||
393 : | print3(REFLISTS,"Ref\n list: "); | ||
394 : | |||
395 : | print4(TLIMITCHECK,"Limit Checks for Continuations Only: "); | ||
396 : | print4(ALIMITCHECK,"Limit Checks for Other allocations: ") | ||
397 : | |||
398 : | end (* fun print_profile_info *) | ||
399 : | |||
400 : | |||
401 : | fun reset() = (print "New alloc profvec, size "; | ||
402 : | print (Int.toString PROFSIZE); print "\n"; | ||
403 : | Unsafe.setPseudo(Array.array(PROFSIZE,0),PROFREG)) | ||
404 : | |||
405 : | end (* toplevel local *) | ||
406 : | end (* structure AllocProf *) | ||
407 : | |||
408 : | (* | ||
409 : | * $Log: allocprof.sml,v $ | ||
410 : | monnier | 93 | * Revision 1.1.1.1 1998/04/08 18:39:46 george |
411 : | * Version 110.5 | ||
412 : | monnier | 16 | * |
413 : | *) |
root@smlnj-gforge.cs.uchicago.edu | ViewVC Help |
Powered by ViewVC 1.0.0 |