aboutsummaryrefslogtreecommitdiff
path: root/Tools/MathematicaMisc/Profile.m
diff options
context:
space:
mode:
authorIan Hinder <ian.hinder@aei.mpg.de>2011-10-13 02:31:51 +0200
committerIan Hinder <ian.hinder@aei.mpg.de>2011-10-28 18:47:56 +0200
commitaddefdfd556a2e33f341bc0dca3e751a0581b3b5 (patch)
treee6c13c96ad7095bea1f04bac76349d039d739262 /Tools/MathematicaMisc/Profile.m
parent2ccff5f0f918ff97dc7041ee3b823432d7848501 (diff)
Add Profile.m for profiling Mathematica functions
Diffstat (limited to 'Tools/MathematicaMisc/Profile.m')
-rw-r--r--Tools/MathematicaMisc/Profile.m113
1 files changed, 113 insertions, 0 deletions
diff --git a/Tools/MathematicaMisc/Profile.m b/Tools/MathematicaMisc/Profile.m
new file mode 100644
index 0000000..8df42b8
--- /dev/null
+++ b/Tools/MathematicaMisc/Profile.m
@@ -0,0 +1,113 @@
+(* Copyright (C) 2010 Ian Hinder and Barry Wardell *)
+
+BeginPackage["Profile`"];
+
+Profile;
+ProfileTime;
+ProfileCount;
+ClearProfile;
+Timer;
+GetTimers;
+RemoveTimers;
+ThresholdTimers;
+PrintTimerTree;
+CoalesceTimers;
+
+Begin["`Private`"];
+
+ClearProfile[] :=
+ Module[{},
+ Clear[ProfileTime];
+ Clear[ProfileCount]];
+
+SetAttributes[Profile, HoldAll];
+
+Profile[name_, code_] :=
+ Module[{time, result, name2, result2, subTimers},
+ name2 = Evaluate[name];
+ {result2,subTimers} = Reap[{time, result} = AbsoluteTiming[ReleaseHold[code]]];
+ If[Head[ProfileTime[name2]] === ProfileTime, ProfileTime[name2] = 0.0];
+ If[Head[ProfileCount[name2]] === ProfileCount, ProfileCount[name2] = 0];
+ ProfileTime[name2] += time;
+ ProfileCount[name2] += 1;
+ Sow[Timer[name2,time,If[subTimers === {}, {}, subTimers[[1]]]]];
+ result];
+
+(* Profile[n_, x_] := x; *)
+
+(* The code below is a prototype for handling a tree of timer
+ information from Profile. It needs to be tidied up and a good
+ interface defined. Example of use:
+
+ {result, timers} = Reap@MyProfile["Total", <code>];
+
+ treeView@addUntimed@
+ Timer[timers[[1, 1, 1]], timers[[1, 1, 2]],
+ addTimers[timers[[1, 1, 3]], sameq, plus]]
+*)
+
+treeView[t : Timer[n_, v_, c_]] :=
+ Module[{},
+ If[c === {},
+ Row[{" ", v, " ", n}],
+ OpenerView[{Row[{v, " ", n}],
+ Column[treeView /@ c]}, True]]]
+
+(* Take a list and, for all the members which are "sameq" as each \
+other, replace them with the application of "plus" to them *)
+add[l_, sameq_, plus_] :=
+ Map[plus, Gather[l, sameq]];
+
+addTimers[ts_List, sameq_, plus_] :=
+ add[Map[Timer[#[[1]], #[[2]], addTimers[#[[3]], sameq, plus]] &, ts],
+ sameq, plus];
+
+sameq[Timer[n1_, v1_, s1_], Timer[n2_, v2_, s2_]] :=
+ n1 === n2 && Length[s1] == Length[s2] &&
+ And @@ MapThread[sameq, {s1, s2}];
+
+plus[ts_List] :=
+ Timer[ts[[1, 1]], Plus @@ Map[#[[2]] &, ts],
+ MapThread[plus[{##}] &, Map[#[[3]] &, ts]]];
+
+addUntimed[Timer[n_, v_, s_List]] :=
+ If[Length[s] === 0, Timer[n, v, s],
+ Module[{total},
+ total = Plus @@ Map[#[[2]] &, s];
+ Timer[n, v,
+ Append[Map[addUntimed, s], Timer["untimed", v - total, {}]]]]];
+
+SetAttributes[GetTimers, HoldAll];
+GetTimers[expr_] :=
+ Module[
+ {result,timers},
+ {result,timers} = Reap[Profile["Total", expr]];
+ {result, timers[[1,1]]}];
+
+CoalesceTimers[t_Timer] :=
+ addTimers[{t}, sameq, plus][[1]];
+
+(* GetTimers[expr_] := *)
+(* addUntimed[ *)
+(* Timer[timers[[1, 1, 1]], timers[[1, 1, 2]], *)
+(* addTimers[timers[[1, 1, 3]], sameq, plus]]]; *)
+
+RemoveTimers[timers_, remove_List] :=
+ timers //. Table[Timer[name, _, {sub___}] :> sub, {name, remove}];
+
+ThresholdTimers[t:Timer[name_, value_, sub_], threshold_:0.1] :=
+ thresholdTimers[t, threshold*value];
+
+thresholdTimers[t:Timer[name_, value_, sub_], absThreshold_] :=
+ DeleteCases[t, Timer[n_, v_, s_] /; v < absThreshold, Infinity] /.
+ Timer[tt_,v_,{Timer["untimed",_,{}]}] :> Timer[tt,v,{}];
+
+PrintTimerTree[Timer[name_, value_, sub_], indent_:0] :=
+ Module[
+ {},
+ Print[StringJoin@@ConstantArray["| ", indent],"o",PaddedForm[value,{3,2}], " ", name];
+ Map[PrintTimerTree[#, indent+1]&, sub]];
+
+End[];
+
+EndPackage[];