Delay-Wait-Sleep tricks.

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Message
Author
einstein1969
Expert
Posts: 960
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Delay-Wait-Sleep tricks.

#1 Post by einstein1969 » 01 Nov 2013 09:58

Hi to all,

I tried a lot but still have not found a solution. :cry:

Does anyone have any idea on how to do a sleep / wait / delay with a resolution of a few hundredths of a second?

Obviously I'm looking for a solution that uses the least amount of CPU while waiting.

It must also have the possibility to be called multiple times without not too heavy delay in the call.

Einstein1969

aGerman
Expert
Posts: 4678
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Delay-Wait-Sleep tricks.

#2 Post by aGerman » 01 Nov 2013 10:56

Since there is no such built-in function in cmd.exe you have to use an external command. What about PING /W? Of course it takes a few hundred milliseconds to load the process (like any other external tool would need as well).

Regards
aGerman

Magialisk
Posts: 104
Joined: 25 Jul 2013 19:00

Re: Delay-Wait-Sleep tricks.

#3 Post by Magialisk » 01 Nov 2013 10:59

It may not be the best solution, but ping with a wait delay seems to be a very common way of doing this. Other solutions may work only in XP or only in 7, or require external utilities, so this is good enough for me.

The basic format is 'ping -n 1 -w <ms> 1.1.1.1', or any other invalid IP address can be used. Replace <ms> with the number of milliseconds to wait (1000 for 1s, 300 for .3s, etc.).

There is some delay implicit in the launching of ping itself, so if you try '-w 1' you're not going to actually get a 1ms delay, you'll get 1+ whatever the delay of launching ping is, probably in the hundredth's of seconds. So there's a lower bound to this approach is what I'm trying to say, but otherwise it's very flexible.

Since you said you're looking for a few hundredths, it's going to depend on how quickly ping launches. I'd use a macro to time how long it takes ping to start, lets say it's 20ms (2 hundredths), then add an appropriate value for 'w' on top of that to get the total delay you need. With that short of a delay though I'm not sure if it will be fast enough for you. I usually use this in the range of tenths of seconds up to tens of seconds...

Edit: It seems I was too slow and cross-posted with aGerman. At least we gave the same advice :)

aGerman
Expert
Posts: 4678
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Delay-Wait-Sleep tricks.

#4 Post by aGerman » 01 Nov 2013 11:11

At least we gave the same advice :)

Indeed :lol:
Just one thing I'd like to mention:
1.1.1.1 could be a valid IP address. I would rather use an IP address that belongs to a reserved block.
See http://www.rfc-editor.org/rfc/rfc5737.txt

Code: Select all

>nul ping -n 1 -w 5000 192.0.2.0


Regards
aGerman

Squashman
Expert
Posts: 4486
Joined: 23 Dec 2011 13:59

Re: Delay-Wait-Sleep tricks.

#5 Post by Squashman » 01 Nov 2013 13:00

Code: Select all

@echo off
echo %time%
FOR /L %%G in (1 1 10000) do rem nothing
echo %time%

Output

Code: Select all

C:\Users\Squash\Desktop>delay.bat
13:59:50.94
13:59:50.97

einstein1969
Expert
Posts: 960
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: Delay-Wait-Sleep tricks.

#6 Post by einstein1969 » 01 Nov 2013 13:39

Thanks!

This are the problems:

1) I want use few CPU
2) I want misure few hundredths of seconds.

that involve this sub problem: How to misure the CPU usage/load?

For question 2) the problem is that:

Code: Select all

@echo off & setlocal EnableDelayedExpansion

For %%t in (5 50 500 1000 1500) do (

   set time_idle_ms=%%t
   set runs=10
   (
   set t0=!time!
   for /L %%p in (1,1,!runs!) do >nul ping -n 1 -w !time_idle_ms! 192.0.2.0
   set t1=!time!
   )

   for /F "tokens=1-8 delims=:.," %%a in ("!t0: =0!:!t1: =0!") do set /a "a=(((1%%e-1%%a)*60)+1%%f-1%%b)*6000+1%%g%%h-1%%c%%d, a+=(a>>31) & 8640000"

   set /a average_time=a*10/runs
   echo(Input:!time_idle_ms! ms - Output: Average time !average_time! ms
)


Output:

Code: Select all

Input:5 ms - Output: Average time 473 ms
Input:50 ms - Output: Average time 498 ms
Input:500 ms - Output: Average time 499 ms
Input:1000 ms - Output: Average time 1050 ms
Input:1500 ms - Output: Average time 1500 ms


There is a problem with ping?

on windows 7 32 bit

Einstein1969
Last edited by einstein1969 on 01 Nov 2013 13:46, edited 1 time in total.

einstein1969
Expert
Posts: 960
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: Delay-Wait-Sleep tricks.

#7 Post by einstein1969 » 01 Nov 2013 13:40

Squashman wrote:

Code: Select all

@echo off
echo %time%
FOR /L %%G in (1 1 10000) do rem nothing
echo %time%

Output

Code: Select all

C:\Users\Squash\Desktop>delay.bat
13:59:50.94
13:59:50.97


I do not want to wait with total consumption of cpu.

Magialisk
Posts: 104
Joined: 25 Jul 2013 19:00

Re: Delay-Wait-Sleep tricks.

#8 Post by Magialisk » 01 Nov 2013 14:52

Wow you taught me something new this afternoon!

Not only did I verify the results that you posted exactly, but I also seem to have confirmed that ping -w rounds the input down to the closest 500ms interval. This is crazy, I can't believe I never noticed this before. I'm on Win7 64-bit, btw. The company upgraded my XP machine recently, so I can't say whether it used to work in XP or if I've just been blind to the rounding all along. I really hope someone will prove the former before I completely look the fool :oops:

>pingtest
Ping -w 600 Elapsed Time: 00:00:00.44
Ping -w 650 Elapsed Time: 00:00:00.49
Ping -w 700 Elapsed Time: 00:00:00.49
Ping -w 750 Elapsed Time: 00:00:00.49
Ping -w 800 Elapsed Time: 00:00:00.49
Ping -w 850 Elapsed Time: 00:00:00.48
Ping -w 900 Elapsed Time: 00:00:00.48
Ping -w 950 Elapsed Time: 00:00:00.48
Ping -w 1000 Elapsed Time: 00:00:01.00
Ping -w 1050 Elapsed Time: 00:00:00.99
Ping -w 1100 Elapsed Time: 00:00:00.98
Ping -w 1200 Elapsed Time: 00:00:00.98
Ping -w 1300 Elapsed Time: 00:00:00.98
Ping -w 1400 Elapsed Time: 00:00:00.98
Ping -w 1500 Elapsed Time: 00:00:01.48
Ping -w 1700 Elapsed Time: 00:00:01.56
Ping -w 1900 Elapsed Time: 00:00:01.48
Ping -w 2100 Elapsed Time: 00:00:01.98
Ping -w 2300 Elapsed Time: 00:00:01.98
Ping -w 2600 Elapsed Time: 00:00:02.48
Ping -w 2900 Elapsed Time: 00:00:02.49
Ping -w 3100 Elapsed Time: 00:00:02.98

Forget everything I said about how "flexible" ping is, it seems it's time to find another technique :!:

Squashman
Expert
Posts: 4486
Joined: 23 Dec 2011 13:59

Re: Delay-Wait-Sleep tricks.

#9 Post by Squashman » 01 Nov 2013 15:31

einstein1969 wrote:I do not want to wait with total consumption of cpu.

Are you saying that the FOR command uses 100% of the cpu when it runs.

einstein1969
Expert
Posts: 960
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: Delay-Wait-Sleep tricks.

#10 Post by einstein1969 » 01 Nov 2013 17:40

Squashman wrote:
einstein1969 wrote:I do not want to wait with total consumption of cpu.

Are you saying that the FOR command uses 100% of the cpu when it runs.


Yes. On my machine if i use the "FOR ... rem" the CPU is closed to 100% usage (single core)

carlsomo
Posts: 91
Joined: 02 Oct 2012 17:21

Re: Delay-Wait-Sleep tricks.

#11 Post by carlsomo » 01 Nov 2013 17:50

Here is an accurate delay routine, but it uses CPU

@echo off&goto :start
:Delay milliseconds
echo.Delay milliseconds
echo.Delays for the specified # of milliseconds
echo.Always accurate to within 10 milliseconds
echo.Returns error of precision in milliseconds
echo.Requires %%time%% variable in military format to work
exit /b 1
:start
if [%1]==[] goto :Delay Syntax
if /i %1 geq 600000 goto :Delay Syntax
setlocal enableextensions
set correct=0
set /a msecs=%1+5
if /i %msecs% leq 20 set /a correct-=2
set time1=%time: =%
set /a tsecs=%1/1000 2>nul
set /a msecs=(%msecs% %% 1000)/10
for /f "tokens=1-4 delims=:." %%a in ("%time1%") do (
set hour1=%%a&set min1=%%b&set sec1=%%c&set "mil1=%%d"
)
if /i %hour1:~0,1% equ 0 if /i "%hour1:~1%" neq "" set hour1=%hour1:~1%
if /i %min1:~0,1% equ 0 set min1=%min1:~1%
if /i %sec1:~0,1% equ 0 set sec1=%sec1:~1%
if /i %mil1:~0,1% equ 0 set mil1=%mil1:~1%
set /a sec1+=(%hour1%*3600)+(%min1%*60)
set /a msecs+=%mil1%
set /a tsecs+=(%sec1%+%msecs%/100)
set /a msecs=%msecs% %% 100
::check for midnight crossing
if /i %tsecs% geq 86400 set /a tsecs-=86400
set /a hour2=%tsecs% / 3600
set /a min2=(%tsecs%-(%hour2%*3600)) / 60
set /a sec2=(%tsecs%-(%hour2%*3600)) %% 60
set /a err=%msecs%
if /i %msecs% neq 0 set /a msecs+=%correct%
if /i 1%msecs% lss 20 set msecs=0%msecs%
if /i 1%min2% lss 20 set min2=0%min2%
if /i 1%sec2% lss 20 set sec2=0%sec2%
set time2=%hour2%:%min2%:%sec2%.%msecs%
:wait
set timen=%time: =%
if /i %timen% geq %time2% goto :end
goto :wait
:end
for /f "tokens=2 delims=." %%a in ("%timen%") do set num=%%a
if /i %num:~0,1% equ 0 set num=%num:~1%
set /a err=(%num%-%err%)*10
endlocal&exit /b %err%


einstein1969
Expert
Posts: 960
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: Delay-Wait-Sleep tricks.

#12 Post by einstein1969 » 01 Nov 2013 18:25

aGerman wrote:Since there is no such built-in function in cmd.exe you have to use an external command. What about PING /W? Of course it takes a few hundred milliseconds to load the process (like any other external tool would need as well).

Regards
aGerman


Thanks aGerman,

Already in another post you pointed out the startup delay of an external process. But apparently the ping uses much less than a few hundred milliseconds. On my machine the initiation of ping seems to use only 10-15 ms(0.01 seconds). I get 9-10 ms with "start /realtime..."

Code: Select all

...
echo Startup time:

(
set t0=!time!
ping > nul
set t1=!time!
)

call :difftime t0 t1 b
set /a time_ms=b*10
echo(single startup: !time_ms! ms

(
set t0=!time!
for /L %%n in (1,1,100) do ping > nul
set t1=!time!
)

call :difftime t0 t1 b

set /a average_time=b*10/100
echo(100 startup: Average time !average_time! ms

(
set t0=!time!
for /L %%n in (1,1,100) do c:\windows\system32\ping.exe > nul
set t1=!time!
)

call :difftime t0 t1 b

set /a average_time=b*10/100
echo(100 startup with path: Average time !average_time! ms

(
set t0=!time!
for /L %%n in (1,1,100) do start "" /REALTIME /WAIT /B c:\windows\system32\ping.exe > nul
set t1=!time!
)

call :difftime t0 t1 b

set /a average_time=b*10/100
echo(100 startup with path + start /REALTIME: Average time !average_time! ms



result:

Code: Select all

Startup time:
single startup: 20 ms
100 startup: Average time 14 ms
100 startup with path: Average time 13 ms
100 startup with path + start /REALTIME: Average time 9 ms


Einstein1969

Magialisk
Posts: 104
Joined: 25 Jul 2013 19:00

Re: Delay-Wait-Sleep tricks.

#13 Post by Magialisk » 01 Nov 2013 23:27

If you look at my reply above, the problem with ping is not that it takes long to start, but that it rounds the wait input to 500ms intervals. At least on Win7 as you and I both found out. It'd be great if someone could verify/disprove that on WinXP, since I'm shocked I've never noticed it before.

foxidrive
Expert
Posts: 6031
Joined: 10 Feb 2012 02:20

Re: Delay-Wait-Sleep tricks.

#14 Post by foxidrive » 02 Nov 2013 00:54

Post your pingtest code...

Magialisk
Posts: 104
Joined: 25 Jul 2013 19:00

Re: Delay-Wait-Sleep tricks.

#15 Post by Magialisk » 02 Nov 2013 01:44

Sorry foxidrive I was at work when I did the pingtest so I don't have the code here. I first just repeated einstein's test (his code is above) because I couldn't believe his results. I got the same thing he got, and started to suspect the 500ms rounding. So I modified his test with new values to test the resolution, but removed the 10x loop and averaging code.

So my FOR looked something like FOR %%i IN (500 550 600 700 900... 2100 2300 ... 3100). Inside the FOR was just calling time macro, ping, and echo the time result.

I figured it wasn't worth running multiple trials and averaging when it was so clearly rounding everything off to 500ms intervals, but I still find it hard to believe that if XP behaved that way I'd have never caught it...

Post Reply