Computer Hope
Microsoft => Microsoft DOS => Topic started by: Frank on August 11, 2008, 03:27:05 AM
-
I also have a calculating problem.
I would like to calculate how long some commands take.
For example:
@echo off
set old=%time%
echo %old%
rem some commands here
echo %old% %time%
set /A delay="%time% - %old%"
echo %delay%
pause
I get an error "Missing operator" with an 18 on the following line.
If I remove the % signs I don't get an error just "-19" on the following line. There must be some sort of a syntax error, but I don't know enough about the set command it to rectify it. It would be nice if I understood the help file (set /?).
Any help would be appreciated.
Frank
-
what does %time% look like?
-
%time% looks like 19:44:16.85
Frank
-
You have to remove the colons, separate out the hours, minutes and seconds, multiply hours x 3600, minutes x 60, and add to seconds to get seconds since midnight, then you can subtract one from another.
-
o/k, this no longer sounds like a job for a batch file.
Frank
-
can be done, I've done it, when I get home in about 6 hrs I'll post it. The big trouble comes when you span midnight. You can get the PC's up time from Windows and use that. Catch me later.
-
Thank you very much.
In 6.5 hours it will be 3:00am here so I will be asleep. But I'll look at the post when I get up.
Thanks again.
Frank
-
Have you got XP pro?
can you use the systeminfo command?
-
Yes, I have Windows XP Pro SP2.
-
Number of seconds since computer was last booted:
for /f "tokens=1-14 delims= " %%A in ('systeminfo ^| find "System Up Time"') do set /a secs=86400*%%D+3600*%%F+60*%%H+%%J
-
Thank you very much.
This is what I did:
@echo off
for /f "tokens=1-14 delims= " %%A in ('systeminfo ^| find "System Up Time"') do set /a secs1=86400*%%D+3600*%%F+60*%%H+%%J
rem some commands to do
for /f "tokens=1-14 delims= " %%A in ('systeminfo ^| find "System Up Time"') do set /a secs2=86400*%%D+3600*%%F+60*%%H+%%J
set /a secs3=secs2-secs1
echo %secs3% seconds taken.
pause
I am not sure I understand the syntax, expecially %%H etc. but it works that's the main thing.
Thanks
-
regarding the syntax - the output of systeminfo is a long string of words separated by spaces, so %%B to %% J are "implicit variables" created by the tokens=1-14 section. Actually, 1-11 would do just as well.
You should note that the actual systeminfo operation takes about 2 seconds, (on my system) so you should subtract that from the second time. You can establish the size of this delay overhead by running the code like this
@echo off
for /f "tokens=1-14 delims= " %%A in ('systeminfo ^| find "System Up Time"') do set /a secs1=86400*%%D+3600*%%F+60*%%H+%%J
rem nothing here
for /f "tokens=1-14 delims= " %%A in ('systeminfo ^| find "System Up Time"') do set /a secs2=86400*%%D+3600*%%F+60*%%H+%%J
set /a secs3=secs2-secs1
echo %secs3% seconds taken.
pause
-
Thanks,
Tried it and the overhead on my system is also 2 seconds.
-
If you do not mind that this will give wrong results if the first time is before midnight, and the second time is after (the next, or a subsequent!) midnight, then this code takes the hours, minutes, seconds, and hundredths of a second in the %time% variable and converts to a figure in milliseconds, and it takes much less than 2 seconds! I would not trust it to beyond around 50 msec though.
@echo off
set ntime=%time%
REM slice up %time%
REM presumes 24 hr clock hh:mm:ss.nn
REM nn=1/100ths of seconds
set hh=%ntime:~0,2%
set mm=%ntime:~3,2%
set ss=%ntime:~6,2%
set cs=%ntime:~9,2%
REM remove any leading zeroes because set /a
REM treats them as indicating octal values
REM and barfs at 08 and 09, understandably!
REM also remove leading space if hour < 10
if "%hh:~0,1%"==" " set hh=%hh:~1,1%
if "%mm:~0,1%"=="0" set mm=%mm:~1,1%
if "%ss:~0,1%"=="0" set ss=%ss:~1,1%
if "%cs:~0,1%"=="0" set cs=%cs:~1,1%
REM now they are all valid integer values, do the arithmetic
set /a msec=3600000*%hh%+60000*%mm%+1000*%ss%+10*%cs%
echo %msec%
say you called it mtime.bat and stored it somewhere on your PATH, you could use it like this
With just that "REM code to be timed" line I am mostly seeing values between 100 & 200 msec with a few as low as 70 or as high as 230.
@echo off
for /f %%T in ('mtime.bat') do set time1=%%T
REM code to be timed
for /f %%T in ('mtime.bat') do set time2=%%T
set /a elapsed=%time2%-%time1%
echo elapsed %elapsed% milliseconds
-
That is cool.
Overhead on my computer is 110-140ms.
This is a much better solution that stepping through a file.
Thanks
Just thought, a dummy run could be made to determine the overhead and then subtract that amount at the end. This would be more acurate. The error that still exists is the variation between successive runs (+- 20ms).
@echo off
rem DO A DUMMY RUN TO FIND THE OVERHEAD
for /f %%T in ('mtime.bat') do set time1=%%T
for /f %%T in ('mtime.bat') do set time2=%%T
set /a overh=%time2%-%time1%
for /f %%T in ('mtime.bat') do set time1=%%T
REM code to be timed
for /f %%T in ('mtime.bat') do set time2=%%T
set /a elapsed=%time2%-%time1%-%overh%
echo elapsed %elapsed% milliseconds
pause
-
The error that still exists is the variation between successive runs (+- 20ms).
I did say, don't trust the system clock to provide more than around 100 msec accuracy
-
I have evolved a better method. Just read the clock at time1 and time 2 and do all the calculating at the end
1. elapsed-calc.bat
@echo off
set time1=%1
set time2=%2
set hh1=%time1:~0,2%
set mm1=%time1:~3,2%
set ss1=%time1:~6,2%
set cs1=%time1:~9,2%
if "%hh1:~0,1%"==" " set hh1=%hh1:~1,1%
if "%mm1:~0,1%"=="0" set mm1=%mm1:~1,1%
if "%ss1:~0,1%"=="0" set ss1=%ss1:~1,1%
if "%cs1:~0,1%"=="0" set cs1=%cs1:~1,1%
set hh2=%time2:~0,2%
set mm2=%time2:~3,2%
set ss2=%time2:~6,2%
set cs2=%time2:~9,2%
if "%hh2:~0,1%"==" " set hh2=%hh2:~1,1%
if "%mm2:~0,1%"=="0" set mm2=%mm2:~1,1%
if "%ss2:~0,1%"=="0" set ss2=%ss2:~1,1%
if "%cs2:~0,1%"=="0" set cs2=%cs2:~1,1%
set /a msec1=3600000*%hh1%+60000*%mm1%+1000*%ss1%+10*%cs1%
set /a msec2=3600000*%hh2%+60000*%mm2%+1000*%ss2%+10*%cs2%
set /a elapsed=%msec2%-%msec1%
echo %elapsed%
Use it like this
@echo off
set time1=%time%
rem code to be timed here
set time2=%time%
for /f %%A in ('elapsed-calc.bat %time1% %time2%') do set elapsed=%%A
echo elapsed time %elapsed% msec
With just that "rem code to be timed here" line I am getting 0 msec showing. Although the time value is shown in msec, obviously there is a 10 msec granularity since the clock only reads to hundredths of a second and in fact I have read that the system clock is not to be trusted to a greater accuracy than around 50 msec.
-
Yes, much easier to implament.
I understand that the time resolution is 10ms. Therefore, no time measurement can be more accurate than within 10ms. But as you say, if the clock accuracy or repeatability is only within 50ms, then that is the most accurate this system can measure.
Since I am trying to measure between 2 and 10 seconds, an error of 50ms is of no consequence.
Thank a lot for these ideas.
-
Frank, I was up early this morning, and I discovered that my code is broken when the hour is less than 10. Although the system time string has a a leading space, this is stripped off when it is passed as a parameter to a batch file, unless:
1. You enclose it in quotes
2. You then dequote it in the batch file
See here
1. elapsed-calc.bat
@echo off
REM remove surrounding quotes (if any)
set time1=%~1
set time2=%~2
set hh1=%time1:~0,2%
set mm1=%time1:~3,2%
set ss1=%time1:~6,2%
set cs1=%time1:~9,2%
if "%hh1:~0,1%"==" " set hh1=%hh1:~1,1%
if "%mm1:~0,1%"=="0" set mm1=%mm1:~1,1%
if "%ss1:~0,1%"=="0" set ss1=%ss1:~1,1%
if "%cs1:~0,1%"=="0" set cs1=%cs1:~1,1%
set hh2=%time2:~0,2%
set mm2=%time2:~3,2%
set ss2=%time2:~6,2%
set cs2=%time2:~9,2%
if "%hh2:~0,1%"==" " set hh2=%hh2:~1,1%
if "%mm2:~0,1%"=="0" set mm2=%mm2:~1,1%
if "%ss2:~0,1%"=="0" set ss2=%ss2:~1,1%
if "%cs2:~0,1%"=="0" set cs2=%cs2:~1,1%
set /a msec1=3600000*%hh1%+60000*%mm1%+1000*%ss1%+10*%cs1%
set /a msec2=3600000*%hh2%+60000*%mm2%+1000*%ss2%+10*%cs2%
set /a elapsed=%msec2%-%msec1%
echo %elapsed%
2. Example of use in batch
@echo off
set time1=%time%
REM code to be timed here
set time2=%time%
REM surround time strings with quote marks
REM line edited to correct error found by Frank
for /f %%A in ('elapsed-calc.bat "%time1%" "%time2%"') do set elapsed=%%A
echo elapsed time %elapsed% msec
3. From the command line using command grouping (you did know about that?) to avoid typing delays when setting start & finish times
S:\Test>(
More? set tt1=
More? set tt2=
More? set tt1=%time%
More? wget -q http://www.programacion-tdt.com/Canal_24h.html
More? set tt2=%time%
More? elapsed-calc "%tt1%" "%tt2%"
More? )
15000
Command grouping works like this (apologies if you know this already!)
At the prompt you type an opening parenthesis ( + Enter. The command processor responds with More? and you type a command or program name & hit Enter & you get another More? prompt and so on until you type a closing parenthesis ) + Enter at which point the whole stored series of commands is executed in sequence almost as if they were in a batch file, with some differences obviously. (E.g. no multiline parenthetical expressions.)
-
I think that the new elapsed-calc.bat works. but this:
for /f %%A in ('elapsed-calc.bat "%time1%" "%time2%"^>nul') do set elapsed=%%A
doesn't. the %elapsed% returns just a space (" ").
Using the previous version:
for /f %%A in ('elapsed-calc.bat %time1% %time2%') do set elapsed=%%A
does work, at least after 10:00am. I'll try it tomorrow morning also.
Thanks for the command grouping. I know about it (now).
-
Yes you are right.
The problem was the ^>nul which is not only unnecessary but harmful.
So the calling code looks this
for /f %%A in ('elapsed-calc.bat "%time1%" "%time2%"') do set elapsed=%%A
I just tested it
-
Well done.
That did it.
Thanks a lot.