• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 264
  • Last Modified:

Need a Hi-Res timer for use in NT/95/98

I'm looking for some kind of delay routine that's very accurate across processor speeds.  I heard a rumor that the Pentium has an instruction that returns a 64-bit number in nanoseconds?
Does someone have a practical example of it using an inline asm, for compilation in MSVC?

I've tried the 'Zen Timer' routine, but NT doesn't like it  much.  It's resolution is perfect for my use on a '95/'98 machine, but I'm looking for an NT compatible one.

Thanks,
Adam Rudolph

P.S. - I'll give you billing in the freeware program I'm writing.
0
arudolph
Asked:
arudolph
  • 5
  • 4
  • 2
  • +1
1 Solution
 
arudolphAuthor Commented:
Adjusted points to 200
0
 
snoeglerCommented:
To access the Pentium/AMD/Cyrix performance counters:

QueryPerformanceCounter() - gives you a 64bit int of the actual value
QueryPerformanceFrequency() - frequency for the counter

The multimedia functions (res 1msec, not 55msec like GetTickCount()):

timeSetEvent
timeKillEvent
timeBeginPeriod
timeEndPeriod
timeGetTime
timeGetSystemTime

The online docs are pretty good on these functions, but if you need further explanation, i
can give you some more information :)
0
 
arudolphAuthor Commented:
Although your suggestion works, it's a little slow.  By using the QueryPerformanceCounter function, it populates a LARGE_INTEGER structure.  This takes time.  I'd prefer to bypass the WINAPI call completely and use the (RTDSC?) machine language function directly.  It will take fewer clock ticks to do it this way, and I'd get a cleaner timer whose accuracy will be the same on slower Pentium's.
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
snoeglerCommented:
Try it ... RTDSC is a ring 0 operation, you'll need to write a device driver for it.
Try getting the DDK from MSDN.
0
 
snoeglerCommented:
BTW: If you're trying to measure some benchmark - if the time your benchmark takes goes
over 1000msec, the relative error caused by delays thru QueryPerformancyCounter() is
somewhat below 1*10^(-6). Also, the interrupts thru window during your benchmark disturb
the result much much more as the time QueryPerformanceCounter() takes.
For what do you need this timing information?
0
 
arudolphAuthor Commented:
I'm looking for a timer routine for game programming.  Initially, I've written a game to emulate the old arcade game 'Breakout', so this routine is used for timing the ball motion.  The 'Zen Timer' routine's resolution works well for this purpose (On dos/w3.1/'95/'98) although even it's too slow for a 486.  Not a big deal.  The first attempt at coding this is out on the 'net: http://jr.ne.mediaone.net/BustOut if you are interested in what this is being used for.  The QueryPerformanceCounter seems to take too long when executed twice to give the smallest wait time for the quickest ball motion.  This is why I was looking for in-line asm code to perform this function.  How many clock cycles could it possibly take to execute the in-line function as compared to the API call?  Alot less I would imagine.  I'll try writing the device driver as you suggest.  Thanks.
0
 
snoeglerCommented:
Take a look at www.sysinternals.com - there you'll find lots of information.
0
 
arudolphAuthor Commented:
Thanks,  please resubmit an answer so I can accept it (giving you da points).
0
 
NakedTimeManCommented:
Hey Arudolph

Use the windows NT performance counter, this counts the a starnge frequency that they (MS) came up with.  BUT is VERY accurate.

It can go even to smaller units than millisecs.

I am including a piece of code that I wrote to time a particular time-critical routine in one of my programs.

P.S.
Send me the "Billing in the freeware program" in beer,  I like to call my programs beerware.

Peace


// TIMING OF THE LOOP 080698ADD
//      double   result, elapsed_time, milliseconds;
//      LARGE_INTEGER Frequency, StartTime, EndTime;
//      QueryPerformanceFrequency(&Frequency);
//      QueryPerformanceCounter(&StartTime);

// Code that you want to time.

//      QueryPerformanceCounter(&EndTime);
//      milliseconds = (USHORT)((EndTime.QuadPart - StartTime.QuadPart)/(Frequency.QuadPart / (__int64)0x00000000000003e8));
//      _strtime(TimeStr);
//      sprintf(DebugStr, "TIME: %s MILLISECONDS ON THE LAST ITERATION: %5.5f ",TimeStr, milliseconds);
//      PRINTDEBUG (1000, DebugStr);
// TIMING OF THE LOOP 080698ADD

0
 
arudolphAuthor Commented:
Need the assembly code.

QueryPerformanceCounter() takes too long to populate the LARGE_INTEGER structure.

Thanks
0
 
gugaCommented:
This a simple example of Long Timer but it count ticks of processor only. You need tune this timer.

#include <stdio.h>

#define rdtsc __asm _emit 0x0F __asm _emit 0x31

typedef struct _T
{
      unsigned long int low;
      unsigned long int high;
} T;

void _get_rdtsc(T* x);

void main()
{
      T c1,c2;
      c1.low=0;
      c1.high=0;
      c2.low=0;
      c2.high=0;
      _get_rdtsc(&c1);
      printf("%X",c1.low);
      _get_rdtsc(&c2);
      printf("Ticks of processor:=%X\n",c2.low - c1.low);
}
void _get_rdtsc(T* x)
{
      _asm
      {
            mov esi,x
            rdtsc
            mov [esi],eax
            mov [esi+4],edx
      }
}
0
 
gugaCommented:
Tuning:
 _get_rdtsc(&c1);
 delay(1000);
 _get_rdtsc(&c2);
 time_of_tick=1.0/((float)(c2.low - c1.low));

I don't sure that high word is unused. This progs is simple example only.
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

  • 5
  • 4
  • 2
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now