Solved

QueryPerformanceCounter Problem ?

Posted on 2008-10-21
11
1,161 Views
Last Modified: 2013-12-04
I have used QueryPerformanceCounter & QueryPerformanceFrequency to detect System uptime, and it seemed to have worked, -well, until this morning that is.

Now, I am getting an uptime of 1 hour 20minutes and change, even though system has been up for over three days (Both systemInfo and "net statistics workstation" correctly identify that system has been up for three days plus). Nothing of significance really happened an hour and 20 minutes ago. (I have been logged in for the last three hours !).

I recall that PerformanceCounter may be off by a few clicks on multi-core/processor machines, but this is a an error of about 80 hours.  Can someone tell me why the following code doesn't work ?

function GetPerformanceCounterTick: Int64;
 
var PCount: Int64;
begin;
  if QueryPerformanceCounter(PCount) then Result := PCount
  else raise exception.create('QueryPerformanceCounter Error');
end;
 
function GetTimerFrequency: Int64;
 
var Frequency: Int64;
begin
  if QueryPerformanceFrequency(Frequency) then Result := Frequency
  else raise exception.create('QueryPerformanceFrequency Error');
end;
 
 
function SystemUptime:string;
 
var f, t : int64;
    r, d, h, m, s : word;
 
begin;
  f := GetTimerFrequency;
  t := GetPerformanceCounterTick;
  r := t div f; // in seconds
  s := r mod 60;  r := r div 60;
  m := r mod 60;  r := r div 60;
  h := r mod 60;  r := r div 24;
  d := r;
  if d >0 then result := Format('%3d Days %2d Hours %2d Minutes %2d Seconds', [d, h, m, s])
  else if h > 0 then result := Format('%2d Hours %2d Minutes %2d Seconds', [h, m, s])
  else if m > 0 then result := Format('%2d Minutes %2d Seconds', [m, s])
  else result := Format('%2d Seconds', [s])
end;

Open in new window

0
Comment
Question by:ahalya
  • 4
  • 3
  • 2
  • +1
11 Comments
 
LVL 31

Assisted Solution

by:Zoppo
Zoppo earned 200 total points
ID: 22767558
Hi ahalya,

I'm not sure if this is relevant here (since I didn't test anything), but shouldn't be the calculation of hours like this?:
>   h := r mod 24;  r := r div 24;

ZOPPO
0
 
LVL 37

Accepted Solution

by:
Geert Gruwez earned 300 total points
ID: 22767648
0
 
LVL 7

Author Comment

by:ahalya
ID: 22768311
Zoppo:

No, we are going from minutes to hours, so I think my caculations are OK. I'll check thatand get back if there are any errors in it.

Geert:
I am using int64 (which is 64 bit) except for days, hours, minutes and seconds.  I see your point that I might be crossing the 32-bit boundary on seconds (86400 in a day). I'll check it and let you know.  (I just rebooted my computer, so it'll have to wait for a day). Thanks.



0
Live: Real-Time Solutions, Start Here

Receive instant 1:1 support from technology experts, using our real-time conversation and whiteboard interface. Your first 5 minutes are always free.

 
LVL 31

Expert Comment

by:Zoppo
ID: 22768478
Hm - are you sure about the calculation? IMO when that mentioned line is reached 'r' is the number of hours, right? If so then the hours are reminder of division through hours a day, so 24 ...

Here a step by step calculation:

// let's assume r = 180330 (50 hours, 5 minutes and 3 seconds)
  s := r mod 60;  r := r div 60;
// now s == 30, r == 3005
  m := r mod 60;  r := r div 60;
// now m == 5, r == 50

Now, next line as you have it
{
    h := r mod 60;  r := r div 24;
  // now h == 50, r = 2
}
Here the same with 'mod 24'
{
    h := r mod 24;  r := r div 24;
  // now h == 2, r = 2
}

BTW, I don't believe this has to do with the main problem ...

Regards,

ZOPPO
0
 
LVL 7

Author Comment

by:ahalya
ID: 22769544
Sorry Zoppo.  I wasn't paying attention.

I said "we are going from minutes to hours," which wasn't what you were pointing out (we are going from hours to days).

Yes, this doesn't have anything to do with the issue, but pretty important nevertheless.  Thanks for correcting me. I'll divide the points upon resolving the other issue.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 22769793
>>>> No, we are going from minutes to hours, so I think my caculations are OK.
you are wrong and Zoppo was right. Modulo 60 returns a number between 0 and 59 what obviously is wrong when counting hours.

>>>> BTW, I don't believe this has to do with the main problem ...

Probably not as the days were 0, right?

>>>> Can someone tell me why the following code doesn't work ?
I have a guess. I'll assume the counter counts in nanoseconds. Then for one day the QPC would count about 86 billion what is 20 times of a 32 bit maximum. I assume that mod and div return a 32 bit integer. So in 3 days we will have 60 times a 32bit divided by 60. Hence we have reached the 32bit boundary stored in the seconds.
 
0
 
LVL 31

Expert Comment

by:Zoppo
ID: 22772689
> Probably not as the days were 0, right?
Yes, exactly ...

About the 32-bit problem - I agree with itsmeandnobodyelse ... maybe declaring the 'r' as int64 could solve the problem.

ZOPPO
0
 
LVL 37

Expert Comment

by:Geert Gruwez
ID: 22773913
i agree with zoppo,

you have a mix of types of variables
and maybe they all get converted to word on the line

r := t div f; // in seconds
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 22774297
>>>> I'll assume the counter counts in nanoseconds.
It is microseconds not nanoseconds.
0
 
LVL 31

Expert Comment

by:Zoppo
ID: 22776790
What's the value of 'f'?
0
 
LVL 7

Author Comment

by:ahalya
ID: 22780994
Thanks Geert_Gruwez & Zoppo,

1.  The trouble was in the type of 'r', which is limited at 65535, but a day has 86400 seconds. I have revised it to int64.

2. The count is a tick (frequency ticks per second), and not really nanoseconds or microseconds. In a 2.4Ghz machine you get 2400000000 ticks per second.

0

Featured Post

Gigs: Get Your Project Delivered by an Expert

Select from freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely and get projects done right.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…

776 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question