views:

1108

answers:

6

I'm wonderin' how I can 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
+1  A: 

You can't do time arithmetic directly in batch scripting, so you'll either need an external program to calculate the time difference, or extract each part of the time and do arithmetic that way.

Take a look at the bottom of this forum thread for an example of how to do the latter.

I also assume it's a typo, but you do want to be sure to set endtime after processing.

lc
+1  A: 

My own personal preference is to install Cygwin and use the time command but, if you actually have to do it as a batch file, you can't just subtract the strings, you have to treat them as parts.

The following script will time a 10-second ping command with the ability to cross a single day boundary without getting tied up in negative numbers. A slight enhancement would allow it to cross many day boundaries.

@echo off
setlocal enableextensions enabledelayedexpansion
set starttime=%time%
ping -n 11 127.0.0.1 >nul: 2>nul:
set endtime=%time%

set /a hrs=%endtime:~0,2%
set /a hrs=%hrs%-%starttime:~0,2%

set /a mins=%endtime:~3,2%
set /a mins=%mins%-%starttime:~3,2%

set /a secs=%endtime:~6,2%
set /a secs=%secs%-%starttime:~6,2%

if %secs% lss 0 (
    set /a secs=!secs!+60
    set /a mins=!mins!-1
)
if %mins% lss 0 (
    set /a mins=!mins!+60
    set /a hrs=!hrs!-1
)
if %hrs% lss 0 (
    set /a hrs=!hrs!+24
)
set /a tot=%secs%+%mins%*60+%hrs%*3600

echo End     = %endtime%
echo Start   = %starttime%
echo Hours   = %hrs%
echo Minutes = %mins%
echo Seconds = %secs%
echo Total   = %tot%

endlocal
paxdiablo
+1  A: 

This is kind of tangential, but it may help you out.

Microsoft has a timeit.exe program that works more or less like an enhanced version of the unix 'time' command. It comes in the Windows Server 2003 Resource Kit, and it has pretty much replaced all the times I've wanted to do something like what you're suggesting.

It may be worth a look.

Dan Olson
+1  A: 

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

set t0=%time%

rem do something here.... but probably with more care about quoting ;-)
%1 %2 %3 %4 %5 %6 %7 %8 %9

set t=%time%

rem make t0 into a scaler in 100ths of a second
set h=%t0:~0,2%
set m=%t0:~3,2%
set s=%t0:~6,2%
set c=%t0:~8,2%
set /a starttime = %h% * 360000 + %m% * 6000 + 100 * %s% + %c%

rem make t into a scaler in 100ths of a second
set h=%t:~0,2%
set m=%t:~3,2%
set s=%t:~6,2%
set c=%t:~8,2%
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 Script took %runtime%0 ms to complete

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...

RBerteig
+1 for going the extra mile... can you explain the set /a business (booted to Linux currently)
ojblass
set /a does arithmetic in Batch. What he does here is reducing everything to 1/100 of a second. Afterwards you can simply subtract them since they're both just numbers.
Joey
You might want to do all the math after your command executed, though ... math in cmd isn't exactly fast so just store the start time and fiddle around with it after your command has ended so it doesn't get counted to the time of the command. Dunno whether it makes a difference, apparently not
Joey
@Johannes, good point... the start time accounting should be done after the end time snapshot. I'll revise the code.
RBerteig
set /a is an extension in the "new" CMD.EXE language that quietly replaced COMMAND.COM when NT was released. Lots of the old commands got new features, but it seems like noone noticed since there is hardly any documentation other than starting from CMD /? at a CMD prompt.
RBerteig
A: 

Yeah as everyone guessed it was a typo lol. it was sposed to go @ the end.

I'll test out peoples suggestions. You people rock! :) Cheers for the help

A: 

@Pax Your answer worked like clockwork! Well done! I have one question though. I'm tryin' to configure the output of the time.

echo Hours   = %hrs% hrs %mins% mins & %secs% secs

That doesn't want to work for me. The '&' stuffs it all up. How can I put the & in there without stuffin' up the code? it comes back with an error with the &. I tried to put "" around it, but then the & displayed with the "" around it, and I don't want that.

It looks weird with 'and' instead of '&'. Is there any possible way? This may seem like an easy question for most.. Please don't flame me lol =)

Awesome work you guys do here. Keep it up.

aphoria
What aphoria said. Quoting in CMD.EXE is really screwball...
RBerteig
@methical, better SO etiquette would be to either edit the original question with new information, or to start a new question. Answers don't make a good vehicle for conversations, or for new questions.
RBerteig