Jump to content

Sleep down to 100 Nano seconds


monoceres
 Share

Recommended Posts

My god I was surprised when I found this function, it's frickin' awesome.

It allows you to sleep down to 100 nanoseconds!

UDF:

; #FUNCTION#;===============================================================================
;
; Name...........: _HighPrecisionSleep()
; Description ...: Sleeps down to 0.1 microseconds
; Syntax.........: _HighPrecisionSleep( $iMicroSeconds, $hDll=False)
; Parameters ....:  $iMicroSeconds      - Amount of microseconds to sleep
;                  $hDll  - Can be supplied so the UDF doesn't have to re-open the dll all the time.
; Return values .: None
; Author ........: Andreas Karlsson (monoceres)
; Modified.......:
; Remarks .......: Even though this has high precision you need to take into consideration that it will take some time for autoit to call the function.
; Related .......:
; Link ..........; 
; Example .......; No
;
;;==========================================================================================
Func _HighPrecisionSleep($iMicroSeconds,$hDll=False)
    Local $hStruct, $bLoaded
    If Not $hDll Then
        $hDll=DllOpen("ntdll.dll")
        $bLoaded=True
    EndIf
    $hStruct=DllStructCreate("int64 time;")
    DllStructSetData($hStruct,"time",-1*($iMicroSeconds*10))
    DllCall($hDll,"dword","ZwDelayExecution","int",0,"ptr",DllStructGetPtr($hStruct))
    If $bLoaded Then DllClose($hDll)
EndFunc

No msdn link for this one, since there is none :P

Note: Even though it supports down to 100 ns sleep don't count on that for being correct in practise because autoit will take some time to call the function (and all the other sutff that are in the UDF). For example on my machine, it took autoit 260 microseconds to call the function.

Edited by monoceres

Broken link? PM me and I'll send you the file!

Link to comment
Share on other sites

My god I was surprised when I found this function, it's frickin' awesome.

It allows you to sleep down to 100 nanoseconds!

UDF:

; #FUNCTION#;===============================================================================
;
; Name...........: _HighPrecisionSleep()
; Description ...: Sleeps down to 0.1 microseconds
; Syntax.........: _HighPrecisionSleep( $iMicroSeconds, $hDll=False)
; Parameters ....:  $iMicroSeconds      - Amount of microseconds to sleep
;                  $hDll  - Can be supplied so the UDF doesn't have to re-open the dll all the time.
; Return values .: None
; Author ........: Andreas Karlsson (monoceres)
; Modified.......:
; Remarks .......: Even though this has high precision you need to take into consideration that it will take some time for autoit to call the function.
; Related .......:
; Link ..........; 
; Example .......; No
;
;;==========================================================================================
Func _HighPrecisionSleep($iMicroSeconds,$hDll=False)
    Local $hStruct, $bLoaded
    If Not $hDll Then
        $hDll=DllOpen("ntdll.dll")
        $bLoaded=True
    EndIf
    $hStruct=DllStructCreate("int64 time;")
    DllStructSetData($hStruct,"time",-1*($iMicroSeconds*10))
    DllCall($hDll,"dword","ZwDelayExecution","int",0,"ptr",DllStructGetPtr($hStruct))
    If $bLoaded Then DllClose($hDll)
EndFunc

No msdn link for this one, since there are none :P

Note: Even though it supports down to 100 ns sleep don't count on that for being correct in practise because autoit will take some time to call the function (and all the other sutff that are in the UDF). For example on my machine, it took autoit 260 microseconds to call the function.

Very interesting. I'm having a bit of a problem finding a use for this.

Do you understand how to use the ZwDelayExecution function with positive values? (I don't.)

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

Very interesting. I'm having a bit of a problem finding a use for this.

Do you understand how to use the ZwDelayExecution function with positive values? (I don't.)

It's not completely useless. Now you can create high precision timers without eating up or the cpu or create very tight loops without getting the CPU up to 100%.

I have no idea how to use positive values. According to this thread (also the thread where I found out about the function) on CodeGuru, positive values are "the absolute time to wake up". I have no idea how to calculate this (maybe nanoseconds since postix or something).

Broken link? PM me and I'll send you the file!

Link to comment
Share on other sites

It's not completely useless. Now you can create high precision timers without eating up or the cpu or create very tight loops without getting the CPU up to 100%.

I have no idea how to use positive values. According to this thread (also the thread where I found out about the function) on CodeGuru, positive values are "the absolute time to wake up". I have no idea how to calculate this (maybe nanoseconds since postix or something).

Crazy...

Nanoseconds = ?

Microseconds = ?

I'm a newb...

Link to comment
Share on other sites

Microsecond = 1/1,000,000th of a second (one millionth)

Nanosecond = 1/1,000,000,000th of a second (one billionth)

The ms usually referred to in computer languages is millisecond, or one thousandth of a second.

Nanosecond precision is , well, wow.

Link to comment
Share on other sites

Oh, you need to study the SI prefixes :P

I have a zeptosecond script :P

Lol... Sorry, I should have thought about just looking those up again....

:o

Since I'm a idiot. How did you measure the time it took for that to process?

Edited by Szhlopp
Link to comment
Share on other sites

Just a question, why would you want to pause for a 100 nanoseconds? I can't see a real use for that much precision... :P

But otherwise this is awesome!

Edited by BrettF
Link to comment
Share on other sites

I have a zeptosecond script :P

Lol... Sorry, I should have thought about just looking those up again....

:zorro:

Since I'm a idiot. How did you measure the time it took for that to process?

Very simple:

$dll=DLlOpen("ntdll.dll")
$timer=TimerInit()
_HighPrecisionSleep(2*1000,$dll); Sleep for 2 milliseconds.
MsgBox(0,"",TimerDiff($timer)); If it says for example 2.35 then 350 microseconds was wasted.

:P

Just a question, why would you want to pause for a 100 nanoseconds? I can't see a real use for that much precision... :robot:

But otherwise this is awesome!

Actually, I just tested and 100 nanoseconds of sleep is enough to keep the CPU percentage at 0% on my machine :o

And, Thanks :D

Edited by monoceres

Broken link? PM me and I'll send you the file!

Link to comment
Share on other sites

Hi Monoceres!

This looks really good, I could do with an accurate sleep for a timer I'm working on.

I don't seems to be able to get it to work....am I using it incorrectly?? :

#include <array.au3>

;----- open dll -----
$dll = DllOpen("ntdll.dll")

;----- array of sleeps to test -----
Dim $sleep[6] = [0.1,1,10,50,100,500]

;----- cal HP-sleep for each -----
For $i = 0 to 5
    $t = TimerInit()
    _HighPrecisionSleep($sleep[$i],$dll)
    $sleep[$i] &= " = " & TimerDiff($t)
Next

;----- display array -----
_ArrayDisplay($sleep)


;----- hp sleep by monoceres -----
Func _HighPrecisionSleep($iMicroSeconds,$hDll=False)
    Local $hStruct, $bLoaded
    If Not $hDll Then
        $hDll=DllOpen("ntdll.dll")
        $bLoaded=True
    EndIf
    $hStruct=DllStructCreate("int64 time;")
    DllStructSetData($hStruct,"time",-1*($iMicroSeconds*10))
    DllCall($hDll,"dword","ZwDelayExecution","int",0,"ptr",DllStructGetPtr($hStruct))
    If $bLoaded Then DllClose($hDll)
EndFunc

...I keep getting 15.x ms of sleep back???

- Table UDF - create simple data tables - Line Graph UDF GDI+ - quickly create simple line graphs with x and y axes (uses GDI+ with double buffer) - Line Graph UDF - quickly create simple line graphs with x and y axes (uses AI native graphic control) - Barcode Generator Code 128 B C - Create the 1/0 code for barcodes. - WebCam as BarCode Reader - use your webcam to read barcodes - Stereograms!!! - make your own stereograms in AutoIT - Ziggurat Gaussian Distribution RNG - generate random numbers based on normal/gaussian distribution - Box-Muller Gaussian Distribution RNG - generate random numbers based on normal/gaussian distribution - Elastic Radio Buttons - faux-gravity effects in AutoIT (from javascript)- Morse Code Generator - Generate morse code by tapping your spacebar!
Link to comment
Share on other sites

Hmmm, maybe I'm not using it correctly???

;=============================================
; Testing 3 different types of SLEEP function
;=============================================

#include <array.au3>

;----- results array -----
Dim $results[1]

;----- array of sleeps to test -----
Dim $sleep[6] = [0.1,1,10,50,100,500]

;----- call HP-sleep -----
_ArrayAdd($results,"_HighPrecisionSleep()")
$dll = DllOpen("ntdll.dll")
For $i = 0 to 5
    $t = TimerInit()
    _HighPrecisionSleep($sleep[$i] * 1000,$dll)
    _ArrayAdd($results,$sleep[$i] & " = " & TimerDiff($t))
Next

;----- call accurate sleep by ludocus -----
_ArrayAdd($results,"")
_ArrayAdd($results,"_AccurateSleep()")
For $i = 0 to 5
    $t = TimerInit()
    _AccurateSleep($sleep[$i])
    _ArrayAdd($results,$sleep[$i] & " = " & TimerDiff($t))
Next

;----- call normal sleep -----
_ArrayAdd($results,"")
_ArrayAdd($results,"AutoIt Sleep()")
For $i = 0 to 5
    $t = TimerInit()
    Sleep($sleep[$i])
    _ArrayAdd($results,$sleep[$i] & " = " & TimerDiff($t))
Next

;----- display array -----
_ArrayDisplay($results)


;##### FUNCTIONS #####

;----- hp sleep by monoceres -----
Func _HighPrecisionSleep($iMicroSeconds,$hDll=False)
    Local $hStruct, $bLoaded
    If Not $hDll Then
        $hDll=DllOpen("ntdll.dll")
        $bLoaded=True
    EndIf
    $hStruct=DllStructCreate("int64 time;")
    DllStructSetData($hStruct,"time",-1*($iMicroSeconds*10))
    DllCall($hDll,"dword","ZwDelayExecution","int",0,"ptr",DllStructGetPtr($hStruct))
    If $bLoaded Then DllClose($hDll)
EndFunc

;----- accurate sleep by ludocus -----
Func _AccurateSleep($sTime)
    $timer=TimerInit()
    Do
        $tmp = TimerDiff($timer)
    Until $tmp >= $sTime
EndFunc

See my results:

- Table UDF - create simple data tables - Line Graph UDF GDI+ - quickly create simple line graphs with x and y axes (uses GDI+ with double buffer) - Line Graph UDF - quickly create simple line graphs with x and y axes (uses AI native graphic control) - Barcode Generator Code 128 B C - Create the 1/0 code for barcodes. - WebCam as BarCode Reader - use your webcam to read barcodes - Stereograms!!! - make your own stereograms in AutoIT - Ziggurat Gaussian Distribution RNG - generate random numbers based on normal/gaussian distribution - Box-Muller Gaussian Distribution RNG - generate random numbers based on normal/gaussian distribution - Elastic Radio Buttons - faux-gravity effects in AutoIT (from javascript)- Morse Code Generator - Generate morse code by tapping your spacebar!
Link to comment
Share on other sites

  • 5 months later...

Hi have some problems with your _HighPrecisionSleep funktion.

After a time the sleep time is getting longer and longer in a running script any idea why ?

_HighPrecisionSleep() shouldn't get longer no matter how many times you run it, please make a small (runnable) reproducer that shows the problem and I am sure the problem can be found
Link to comment
Share on other sites

  • 1 month later...

Thank you again, monoceres.

Just for convenience I thought I post this:

$hDll=DllOpen("ntdll.dll")

$init = TimerInit()
_HighPrecisionSleepUnsafe(1000000, $hDll)
ConsoleWrite( TimerDiff($init) )

Func _HighPrecisionSleepUnsafe($iMicroSeconds,$hDll)
    _HighPrecisionSleepRawUnsafe( -1*($iMicroSeconds*10), $hDll )
EndFunc

Func _HighPrecisionSleepRawUnsafe($iMicroSecondsRaw, $hDll)
    $hStruct=DllStructCreate("int64 time;")
    DllStructSetData($hStruct,"time",$iMicroSecondsRaw)
    DllCall($hDll,"dword","ZwDelayExecution","int",0,"ptr",DllStructGetPtr($hStruct))
EndFunc
Link to comment
Share on other sites

For people who want it to be more accurate try this

Global $hDll=DllOpen("ntdll.dll")

Func _HighPrecisionSleep($iMicroSeconds)

Local $hStruct

$hStruct=DllStructCreate("int64 time;")

DllStructSetData($hStruct,"time",-1*($iMicroSeconds*10))

DllCall($hDll,"dword","ZwDelayExecution","int",0,"ptr",DllStructGetPtr($hStruct))

EndFunc

This will be faster at least on my PC. Remember Autoit is still a scripting language.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...