ListFromSamples:
PROC [asd: AcceptSamplesInstance]
RETURNS [ProfileEntryList] = {
ListFromSamples destructively reads the structure produced by AcceptSamples and returns a list of <pc, count> pairs, sorted by increasing pc. The client must not use the old AcceptSamplesInstance instance after this call.
procList: ProfileEntryList ¬ NIL;
FOR next: AcceptSamplesInstance ¬ asd, next.link
WHILE next #
NIL
DO
FOR i: [0..maxAcceptSamples)
IN [0..next.nextIndex)
DO
sample: ProfileEntry = next.samples[i];
new: RefProfileEntry ¬ NEW[ProfileEntry ¬ [pc: sample.pc, count: sample.count]];
procList ¬ CONS[new, procList];
ENDLOOP;
ENDLOOP;
procList ¬ SortProfileEntries[procList];
FreeSamples[asd];
RETURN [procList];
};
OutputFromSamples:
PROC
[out:
STREAM, asd: AcceptSamplesInstance, stats: Stats, line:
ROPE,
modCutoff:
REAL, procCutoff:
REAL, debug:
BOOL ¬
FALSE] = {
totalProcs: NAT ¬ 0;
totalCount: CARDINAL ¬ 0;
modules: NAT ¬ 0;
eachModule: VisitModules = {
IF list #
NIL
THEN {
Some counts found in this module
first: ProcEntry = list.first;
mc: CARDINAL ¬ 0;
entry: ModuleEntry =
NEW[ModuleEntryRep ¬ [
ilse: ilse,
name: name, nameOK: nameOK,
pc: pc, size: size, type: type,
count: 0,
procs: list]];
WHILE list #
NIL
DO
first: ProcEntry = list.first;
fc: CARDINAL = first.count;
list ¬ list.rest;
mc ¬ mc + fc;
totalCount ¬ totalCount + fc;
totalProcs ¬ totalProcs + 1;
ENDLOOP;
entry.count ¬ mc;
modList ¬ CONS[entry, modList];
modules ¬ modules + 1;
};
};
modList: ModuleEntryList ¬ NIL;
modSkipped: CARDINAL ¬ 0;
modCountSkipped: CARDINAL ¬ 0;
tryCutoff: BOOL ¬ modCutoff > 0.0;
bogusList: ProfileEntryList ¬ ModulesFromSamples[
ListFromSamples[asd],
eachModule,
IF debug THEN out ELSE NIL];
toPercent: REAL = 100.0/totalCount;
modList ¬ SortModuleEntriesByCount[modList];
IO.PutF1[out, "-- Leafy output on %g for\n", [time[BasicTime.Now[]]] ];
IO.PutF1[out, " -- %g", [rope[line]]];
IO.PutF1[out, "-- Elapsed seconds: %5.3f", [real[stats.elapsed]]];
IO.PutF1[out, ", bytes allocated: %g", [cardinal[stats.bytesAllocated]] ];
IO.PutF1[out, ", utime: %5.3f", [real[stats.utime]] ];
IO.PutF1[out, ", stime: %5.3f\n", [real[stats.stime]] ];
IO.PutF1[out, "-- Total count: %g", [cardinal[totalCount]] ];
IO.PutF1[out, ", modules with counts: %g", [cardinal[modules]] ];
IO.PutF1[out, ", procs with counts: %g\n", [cardinal[totalProcs]] ];
modules ¬ 0;
FOR each: ModuleEntryList ¬ modList, each.rest
WHILE each #
NIL
DO
me: ModuleEntry = each.first;
mc: CARDINAL = me.count;
list: ProcEntryList ¬ me.procs;
modPerc: REAL = mc*toPercent;
procSkipped: CARDINAL ¬ 0;
countSkipped: CARDINAL ¬ 0;
showProcs: BOOL ¬ TRUE;
IF tryCutoff
AND (modPerc < modCutoff
OR mc < 2)
THEN {
Don't bother to show this module, it's not significant
modSkipped ¬ modSkipped + 1;
modCountSkipped ¬ modCountSkipped + mc;
showProcs ¬ FALSE;
}
ELSE
TRUSTED {
ShowPercent[out, mc, modPerc, ": "];
PutCharStar[out, me.name, '., '←];
IO.PutF1[out, ", startPC: %g", [cardinal[me.pc]] ];
IO.PutF1[out, ", size: %g\n", [cardinal[me.size]] ];
};
WHILE list #
NIL
DO
pe: ProcEntry = list.first;
procName: CharPtr = SymbolNameFromILSymEntry[pe.ilse];
count: CARDINAL = pe.count;
procPerc: REAL = count*toPercent;
list ¬ list.rest;
IF showProcs
THEN {
IF tryCutoff
AND (procPerc < procCutoff
OR count < 2)
AND (procSkipped # 0
OR list #
NIL)
THEN {
Don't show this procedure
procSkipped ¬ procSkipped + 1;
countSkipped ¬ countSkipped + count;
}
ELSE
TRUSTED {
IO.PutRope[out, " "];
ShowPercent[out, count, procPerc, ": "];
PutCharStar[out, procName, 0c, '←];
IO.PutRope[out, "\n"];
};
};
ENDLOOP;
IF showProcs
AND procSkipped # 0
THEN {
IO.PutF1[out, " -- procs skipped: %g, counts skipped: ", [cardinal[procSkipped]] ];
ShowPercent[out, countSkipped, countSkipped*toPercent, "\n"];
};
modules ¬ modules + 1;
ENDLOOP;
IF modSkipped # 0
THEN {
IO.PutF1[out, "-- Modules not shown: %g, counts not shown: ", [cardinal[modSkipped]] ];
ShowPercent[out, modCountSkipped, modCountSkipped*toPercent, "\n"];
};
IF bogusList #
NIL
THEN {
We noticed some bogus pc values, so print them out
bogusCount: CARDINAL ¬ 0;
IF debug
THEN {
bogusList ¬ SortProfileEntries[bogusList];
IO.PutRope[out, "-- Bogus:"];
};
FOR each: ProfileEntryList ¬ bogusList, each.rest
WHILE each #
NIL
DO
first: RefProfileEntry = each.first;
bogusCount ¬ bogusCount + first.count;
IF debug
THEN {
IO.PutF1[out, " %g", [cardinal[first.pc]]];
IF first.count # 1
THEN
IO.PutF1[out, "(%g)", [cardinal[first.count]]];
};
ENDLOOP;
IF debug THEN IO.PutChar[out, '\n];
IO.PutF1[out, "-- Bogus count: %g\n", [cardinal[bogusCount]]];
};
};