14
$\begingroup$

Sometimes I forget to add Timing[] to my evaluation and only notice it once it has already finished. Some of my calculations take hours or even days, so I don't want to restart the entire evaluation just to add Timing[] to it.

Is there a way to know the execution time of my evaluation after it has already finihsed, without relaunching the entire process?

$\endgroup$
  • 2
    $\begingroup$ this may be useful: Extracting notebook history programmatically $\endgroup$ – kglr Jul 8 '18 at 8:35
  • $\begingroup$ If your code generates an Output Cell then you can find the evaluation time as the difference between CellChangeTimes of the Output and Input Cells. $\endgroup$ – Alexey Popkov Oct 30 '18 at 2:40
  • $\begingroup$ @AlexeyPopkov That sounds interesting, can you perhaps give an example in the form of an answer? $\endgroup$ – Klangen Oct 30 '18 at 8:45
  • 1
    $\begingroup$ @Flermat After thinking I must confess that I was mistaken: CellChangeTimes of the Input Cell contains last edititing time, not the time when the Cell was evaluated. So in this way we can get only an upper bound of the evaluation time. $\endgroup$ – Alexey Popkov Oct 30 '18 at 9:39
12
+50
$\begingroup$

The case when the evaluation is finished

Some of my calculations take hours or even days, so I don't want to restart the entire evaluation just to add Timing[] to it.

If your code generates an Output Cell then you can find at least an upper bound of the evaluation time as the difference between last CellChangeTimes of the Output and Input Cells. It can be very close to the actual evaluation time if you edited the Input Cell just before evaluating it. In this case you can simply paste and evaluate the following code right after the Output Cell:

DateDifference @@ 
 Last /@ Flatten /@ 
   CurrentValue[PreviousCell[CellStyle -> #] & /@ {"Input", "Output"}, CellChangeTimes]

The case when the evaluation is still running

If the evaluation is still running you can try to set the EvaluationCompletionAction -> "ShowTiming" option before the evaluation has finished using The Options Inspector (Ctrl+Shift+O):

screenshot1

On the above screenshot this option is set on the $FrontEnd level ("Global Preferences"), but it is sufficient to set it only on the Notebook level for the Notebook where your evaluation is still running.

If you succeed in this, after finishing the evaluation you'll see the timing at the lower left corner of the notebook as shown in the answer by Jason B.:

screenshot2

Note that the timing includes the complete evaluation time, not the time spent after you have set the option! This proves that FrontEnd measures evaluation time even when the option isn't set, and hence it should be theoretically possible to get this information even after finishing the evaluation (but I don't know how).

$\endgroup$
  • $\begingroup$ Excellent answer, thank you! $\endgroup$ – Klangen Oct 30 '18 at 12:42
12
$\begingroup$

Evaluate

SetOptions[$FrontEnd, EvaluationCompletionAction -> "ShowTiming"]

and then the evaluation time for the last evaluation will be shown in the lower left corner of the notebook:

enter image description here

Like many front end options, this setting is sticky. Set it once, and forget it; it also works across all versions of Mathematica installed.

$\endgroup$
  • 3
    $\begingroup$ Too bad there wasn't a way of finding the timing retrospectively. (In this approach, you must evaluate the SetOptions before running the time consuming command). $\endgroup$ – bill s Oct 29 '18 at 20:19
  • 2
    $\begingroup$ That doesn't really seem like a limitation to me. Finding the timing of the currently evaluating cell is an edge case. By using this setting, you get the timing for all future evaluations. $\endgroup$ – Jason B. Oct 30 '18 at 11:38
  • $\begingroup$ @bills I've added new section into my answer where I explain how this option can be set during evaluation. $\endgroup$ – Alexey Popkov Oct 30 '18 at 12:26
7
$\begingroup$

This is not immediately an answer to OP's question but it does provide an initialization code which one can use in all her/his files so that they do not have to worry about forgetting inserting Timing commands.

One can simply define a new variable, say duration, and record the evaluation of each calculation to this variable in the background.

Following code is sufficient for that:

ClearAll[duration,durationTemp];
$PreRead := ((durationTemp = AbsoluteTime[]); Function[#]);
$Post := ((duration[$Line] = AbsoluteTime[] - durationTemp);Function[#]);

What it does is to record the absolute time when the input is given and calculate the time passed when the evaluation finishes. This is done for each calculation, and recorded with input line so that duration[n] gives the time spent for the calculation of Out[n].

As an example:

In[4]:= 1+1
Out[4]= 2
In[5]:= Pause[2]
In[6]:= Pause[5]
?duration

Global`duration
duration[3]=0.000351

duration[4]=0.000115

duration[5]=2.000717

duration[6]=5.000930

This is the most basic form; but one can modify duration function so that it counts in minutes instead of seconds, and it may garbage collect itself (say only keeps last 30 entries).

One can actually easily implement last idea using Associations. Specifically, below code does the same job using associations, and also only keeps last $n$ entries, where $n$ is set by durationLength:

ClearAll[duration, durationLength];
duration = <||>;
durationLength = 3;
$PreRead := (durationTemp = AbsoluteTime[]; Function[#]);
$Post := (If[KeyExistsQ[duration, $Line - durationLength], 
   KeyDropFrom[duration, $Line - durationLength]; 
   AssociateTo[duration, $Line -> AbsoluteTime[] - durationTemp], 
   AssociateTo[duration, $Line -> AbsoluteTime[] - durationTemp]]; 
   Function[#]);

As an example:

In[6]:= 1+1
Out[6]= 2
In[7]:=Pause[1]
In[8]:=Pause[2]
In[9]:=Pause[3]

?duration

Global`duration
duration=<|7->1.000416,8->2.001829,9->3.001157|>

Depending on the conditions, it may actually be a better idea to dedicate a stream to this and let it record the times to a file in the background. For example, one can use OpenWrite[] to create a temporary file per session, but I cannot imagine any scenario for which writing to a file is better than having this variable if the file is to be cleared after session ends (assuming session times are not extremely long). However, if one wants to keep a long record, then dedicating a file for this data and using OpenAppend to add these information to the same file may be useful. For example, if one has a 6 month long project and expects to have thousands of evaluation whose timing information happens to be useful data, then this may be relevant.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.