I have a main function f[x]
that calls three sub-functions:
f1[x_] := x^2;
f2[x_] := x + 5;
f3[x_] := Sin[x];
f[x_] := f1[x] + f2[f3[x]]
(In my real application, the functions are more complicated.)
I would like to time how long f1
, f2
, and f3
take to execute, without re-defining them or f
.
One idea is to temporarily replace f1
with a function that times f1
and uses Sow
to return the time, like this:
With[
{
f1[x_] := Block[{t, z}, {t, z} = AbsoluteTiming[f1[x]]; Sow[t]; Return[z]]
},
Reap[f[x]]
]
Or this:
Block[
{
f1 = Function[x, Block[{t, z}, {t, z} = AbsoluteTiming[f1[x]]; Sow[t]; Return[z]]]
},
Reap[f[x]]
]
(And do the same for f2
and f3
)
However, both these forms produce errors.
Is there a way to temporarily "inject" AbsoluteTiming into a function, and use Sow/Reap to obtain timing information?
Update
It seems that TraceScan was just what I needed:
g[x_] := (Pause[.1]; Cos[x])
h[x_] := (Pause[.2]; Tan[x])
f[x_] := h[x] + Sin[g[x]]
Block[
{list = {}, t},
TraceScan[
(t = Now) &,
f[x],
_g | _h,
(AppendTo[list, {#, Now - t}];) &
];
Column[list]
]
returns
{h[x],0.201649s}
{g[x],0.100481s}
Thanks Carl Woll for your example use of TracePrintEvaluate
!
Reap
why not just directly useAbsolutTiming
? $\endgroup$AbsoluteTiming
because I feel it would distract the reader from the main goal of my code. That is, I would like to perform a timing investigation after the functions have been defined and demonstrated, without modifying them with timing code. $\endgroup$