flat assembler
Message board for the users of flat assembler.

Index > Windows > Question: How do I get real millisecond acuracy.

Author
Thread Post new topic Reply to topic
rxantos



Joined: 19 Jul 2008
Posts: 41
rxantos 07 Aug 2008, 03:52
Is there a way to get real 1 millisecond accuracy (not 15 or 10 milliseconds) withing windows? Basically I need a delay of 1 to 2 miliseconds between 2 operations. One after another is too fast and waiting 15 milliseconds is too slow.

So the maximum granularity of time that I seek is 1 millisecond. Is there a way to get this in windows?

I know that there is the rdtsc instruction that gives the number of ticks. Is there a way of calculating the frequency of the cpu? If I could to that I think I can get the 1 millisecond with a 0.5 millisecond error tolerance that I seek.
Post 07 Aug 2008, 03:52
View user's profile Send private message Reply with quote
f0dder



Joined: 19 Feb 2004
Posts: 3175
Location: Denmark
f0dder 07 Aug 2008, 09:57
Don't do rdtsc - this leads to problems on AMD dualcore machines if your thread gets schedules to another core.

Your best bet is probably timeBeginPeriod() and some manual time polling... but this will obviously hog the CPU.

Windows wasn't really written with realtime use in mind. What are you trying to do? Smile

Oh great, sucky phpBB can't handle parenthesis in URLs? Yay. I'll just leave the post formatted as-is Smile
Post 07 Aug 2008, 09:57
View user's profile Send private message Visit poster's website Reply with quote
Madis731



Joined: 25 Sep 2003
Posts: 2139
Location: Estonia
Madis731 07 Aug 2008, 10:39
The algorithm is relatively easy:
Code:
rdtsc
mov qword[time1],eax:edx
...
...
rdtsc
sub eax:edx,qword[time1]
mov esi,[CPU_ticks_in_ms] ; 2.5GHz CPU has 2500000 here
div esi
;OUT=eax ms
    

The problem is knowing your CPU clock. Intel has algorithms to read this from cpuid, but AMD behaves differently.
Intel also has an HPET on some newer boards if you can use it, but other manufactures don't etc.

EDIT:
The easiest way on non-HT, non-DC, non-IntelSpeedStep machines is to init your CPU_ticks_in_ms on program startup by measuring it to a known value. GetTickCount+1000 for example and then use it in other places of your program.


Last edited by Madis731 on 07 Aug 2008, 10:50; edited 1 time in total
Post 07 Aug 2008, 10:39
View user's profile Send private message Visit poster's website Yahoo Messenger MSN Messenger Reply with quote
f0dder



Joined: 19 Feb 2004
Posts: 3175
Location: Denmark
f0dder 07 Aug 2008, 10:46
Madis: again, DO NOT USE RDTSC FOR TIMING!

It's OK if you want to profile a snippet of code, but you shouldn't use it for production-grade timing. There's the AMD dual-core bug (and no, not everybody will have AMDs fix/hack installed). And then there's the issue of speedstep and similar technologies...
Post 07 Aug 2008, 10:46
View user's profile Send private message Visit poster's website Reply with quote
Madis731



Joined: 25 Sep 2003
Posts: 2139
Location: Estonia
Madis731 07 Aug 2008, 10:53
Smile okay sorry (shame on me), there's a topic on GameDev: http://www.gamedev.net/community/forums/topic.asp?topic_id=321312
HPET I was talking about:
http://en.wikipedia.org/wiki/High_Precision_Event_Timer
Post 07 Aug 2008, 10:53
View user's profile Send private message Visit poster's website Yahoo Messenger MSN Messenger Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8351
Location: Kraków, Poland
Tomasz Grysztar 07 Aug 2008, 11:24
What about local APIC timer?
Post 07 Aug 2008, 11:24
View user's profile Send private message Visit poster's website Reply with quote
DJ Mauretto



Joined: 14 Mar 2007
Posts: 464
Location: Rome,Italy
DJ Mauretto 07 Aug 2008, 17:57
Hello Smile

Local APIC timer use Cpu bus clock + internal register as divider selectable ,
it's not compatible betwen different pc , then i don't think that OS like windows
allow you to access to memory mapped APIC register.
The only way is Windows API or write a kernel mode driver and use 8254 timer Wink

Note: if your software run only on your pc use this:

mov ecx,Delay
@@:
loop @B

It is the perfect timer better of RDTSC ,HPET, APIC and 8254

_________________
Nil Volentibus Arduum Razz
Post 07 Aug 2008, 17:57
View user's profile Send private message Reply with quote
Alphonso



Joined: 16 Jan 2007
Posts: 295
Alphonso 07 Aug 2008, 18:30
Well maybe there's the windows high performance counters... As a very rough example
Code:
include 'win32ax.inc'

.code
  start:
        invoke QueryPerformanceFrequency,Freq
        cmp    eax,0
        je     HPC_Not_Supported

        mov    edx,dword [Freq+4]
        mov    eax,dword [Freq]                  ;Freq = counts per second
        mov    ebx,1000
        div    ebx
        cmp    eax,10
        jl     Sub100us                          ;Resolution is less than 100us
        mov    [msRes],eax                       ;counts per millisecond

        invoke QueryPerformanceCounter,StartTime
        mov    ebx,dword [StartTime]
        add    ebx,[msRes]                       ;ebx=Start time + 1ms in counts

;--------------------------------------------------------------------
  @@:   invoke QueryPerformanceCounter,StopTime
        mov    eax,dword [StopTime]
        sub    eax,ebx
        jl     @b                                ;Check if 1ms has passed yet
;--------------------------------------------------------------------

        mov    edx,dword [StopTime+4]            ;Check actual time
        mov    eax,dword [StopTime]
        sub    eax,dword [StartTime]
        sbb    edx,dword [StartTime+4]
        mov    ebx,1000000
        mul    ebx                               ;edx:eax = counts per microsecond
        mov    ebx,dword [Freq]
        div    ebx                               ;eax = number of microseconds

        invoke wsprintf,Result,'%d us',eax       ;easy/lazy way  Zzz...
        invoke MessageBox,NULL,Result,'Timing',MB_OK
        jmp    @f
  Sub100us:
        invoke  MessageBox,0,'<100us','Low Resolution',MB_OK
        jmp    @f
  HPC_Not_Supported:
        invoke  MessageBox,0,'No performance here..','Error',MB_OK
  @@:   invoke  ExitProcess,0
 .end start

.data
  Freq            dq 0
  StartTime       dq 0
  StopTime        dq 0
  msRes           dd 0
  Result          rb 20    
Seems a bit wasteful of CPU time though.
Post 07 Aug 2008, 18:30
View user's profile Send private message Reply with quote
r22



Joined: 27 Dec 2004
Posts: 805
r22 07 Aug 2008, 23:41
rxantos wrote:
Is there a way to get real 1 millisecond accuracy (not 15 or 10 milliseconds) withing windows? Basically I need a delay of 1 to 2 miliseconds between 2 operations. One after another is too fast and waiting 15 milliseconds is too slow.

So the maximum granularity of time that I seek is 1 millisecond. Is there a way to get this in windows?

I know that there is the rdtsc instruction that gives the number of ticks. Is there a way of calculating the frequency of the cpu? If I could to that I think I can get the 1 millisecond with a 0.5 millisecond error tolerance that I seek.


OPTION 1
The SleepEx function in kernel32.dll will work.
invoke SleepEx, 1, 0

Setting your process / threads priority class to real_time and affinity mask to 1 processor will help.

This is the best you can do without a driver in windows user-land.

OPTION 2
You could also try using the WINMM.DLL functions
timeBeginPeriod
timeEndPeriod
timeSetEvent
and the callback TimeProc
Post 07 Aug 2008, 23:41
View user's profile Send private message AIM Address Yahoo Messenger Reply with quote
Madis731



Joined: 25 Sep 2003
Posts: 2139
Location: Estonia
Madis731 08 Aug 2008, 07:05
The SleepEx is precise to about 1ms, but ONLY after 16ms which I think is the first increment - always! Thread priority and affinity doesn't help there.

When you already guarantee only one CPU, then you can read core clock cycles, which do not change. (Needs a driver)

I think that Microsoft even tells on their site that their high-precision functions don't work that well, if you're not careful Razz
Post 08 Aug 2008, 07:05
View user's profile Send private message Visit poster's website Yahoo Messenger MSN Messenger Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.