How long does a batch file take to execute?

Methical picture Methical · Apr 11, 2009 · Viewed 38k times · Source

How can I write a script to calculate the time the script took to complete?

I thought this would be the case, but obviously not..

@echo off
set starttime=%time%
set endtime=%time%

REM do stuff here

set /a runtime=%endtime%-%starttime%
echo Script took %runtime% to complete

Answer

RBerteig picture RBerteig · Apr 11, 2009

Two things leap out about the original batch file. but neither is going to help in the long run.

  1. Whatever your benchmark method, be sure to capture the start time before the operation, and the end time after the operation. Your sample doesn't do that.

  2. %time% evaluates to something like "12:34:56.78", and the SET /A command can't subtract those. You need a command that produces a simple scalar time stamp.

I was going to say it can't be done, but the batch language is a lot more powerful than it is given credit for, so here is a simple implementation of TIMER.BAT. For the record, Pax beat me to an answer showing the string splitting while I was fiddling around, and Johannes Rössel suggested moving the arithmetic outside of the measured region:

@echo off
setlocal

rem Remeber start time. Note that we don't look at the date, so this
rem calculation won't work right if the program run spans local midnight.
set t0=%time: =0%

rem do something here.... but probably with more care about quoting.
rem specifically, odd things will happen if any arguments contain 
rem precent signs or carets and there may be no way to prevent it.
%*

rem Capture the end time before doing anything else
set t=%time: =0%

rem make t0 into a scaler in 100ths of a second, being careful not 
rem to let SET/A misinterpret 08 and 09 as octal
set /a h=1%t0:~0,2%-100
set /a m=1%t0:~3,2%-100
set /a s=1%t0:~6,2%-100
set /a c=1%t0:~9,2%-100
set /a starttime = %h% * 360000 + %m% * 6000 + 100 * %s% + %c%

rem make t into a scaler in 100ths of a second
set /a h=1%t:~0,2%-100
set /a m=1%t:~3,2%-100
set /a s=1%t:~6,2%-100
set /a c=1%t:~9,2%-100
set /a endtime = %h% * 360000 + %m% * 6000 + 100 * %s% + %c%

rem runtime in 100ths is now just end - start
set /a runtime = %endtime% - %starttime%
set runtime = %s%.%c%

echo Started at %t0%
echo Ran for %runtime%0 ms

You could simplify the arithmetic and be a little more honest about the overall accuracy of this by not bothering with the 100ths of a second part. Here it is in action, assuming you have a sleep command or some other time waster:

C:> TIMER SLEEP 3
Script took 3000 ms to complete
C:> 

Edit: I revised the code and its description as suggested in a comment.

I think that when the NT team replaced COMMAND.COM with CMD.EXE, they thought they wouldn't get away with making it very different. But in effect, it is almost an entirely new language. Many of the old favorite commands have new features if the extensions are enabled.

One of those is SETLOCAL which prevents variables from modifying the caller's environment. Another is SET /A which gives you a remarkable amount of arithmetic. The principle trick I've used here is the new substring extraction syntax where %t:~3,2% means the two characters starting at offset 3 in the value of the variable named t.

For a real shocker, take a look at the full description of set (try SET /? at a prompt) and if that doesn't scare you, look at FOR /? and notice that it can parse text out of files...

Edit 2: Fixed mis-handling of time fields containing 08 or 09 reported by Frankie in comments. Tweaked a couple of things, and added some comments.

Note that there is a glaring oversight here that I'm probably not going to fix. It won't work if the command starts on a different day than it ends. That is, it will do some math related to the time of day and report a difference, but the difference won't mean much.

Fixing it to at least warn about this case is easy. Fixing it to do the right thing is harder.

Edit 3: Fixed error where the %h% is not set properly for single digit hours. This is due to %time% returning " 9:01:23.45". Notice the space. Using %time: =0% replaces the space with a leading zero and %h% will be set correctly. This error only occurred when a script ran from one single digit hour to the next.