11 replies to this topic

### #1polyvertex

Member

• Members
• 32 posts

Posted 09 April 2008 - 10:11 AM

Hi Nick,

I've just downloaded the old open source code from the link provided by "juhana" in this thread to take a quick look on it.

I'm a bit surprised by the implementation of your Timer class...

I remember when I created my own Timer class for my 3D engine, I've end up with approximately the same straight-forward implementation :)
But I've rapidly got some weird timing effects (3D animations went fast, then slow, then fast, etc...), first I thought it was because of my crappy animation system but then I've found that tons of developers had the same problem as mine and it's seems to happen on multi-core platforms only (ex : this GD thread).

I know this is old code so maybe the Timer class in today's SwiftShader is no more the same but I just had to ask you the question : didn't you had any side effect like mine on multi-core platforms with this implementation ?

Maybe it was so long time ago so you could not try it on a multi-core platform, thus my question would become totally irrelevant... :)

### #2Nick

Senior Member

• Members
• 1227 posts

Posted 10 April 2008 - 05:31 PM

That class is no longer used (there's nothing time dependent). But I'd love to know what you discovered exactly and whether you found better alternatives!

### #3polyvertex

Member

• Members
• 32 posts

Posted 10 April 2008 - 10:32 PM

Errr, OK :)

Well, I did not "discovered" so much...
And I think I'd better not to feed the troll again about performance timing and profiling under Windows... :)

AFAIK, performance counters under Windows have 2 well-known problems :
* Too great leaps between 2 calls to QueryPerformanceCounter() (seems to be on every platforms, example here). Here is the MSDN KB article about it.
* The side effect I described due to the fact that each core has its own clock (so the problem occurs only on multi-core platforms, example here)

For clarity, here is "your" implementation (and basically the same as my old one) :
double Timer::seconds()

{

__int64 currentTime;

__int64 frequency;

QueryPerformanceFrequency((LARGE_INTEGER*)&frequency);

QueryPerformanceCounter((LARGE_INTEGER*)¤tTime);

return (double)currentTime / (double)frequency;

}



Now, the most-common-and-recommended-trick :
There is an example implementation in OGRE 3D (Timer::getMilliseconds method at line 119).

As you can see, this is awful, but during my googling trip about this problem, I found nothing better for performance timing.

Maybe someone here use an another trick ?

### #4Kenneth Gorking

Senior Member

• Members
• 939 posts

Posted 10 April 2008 - 11:37 PM

What if the thread the timer is running on runs at half the speed of the other threads?
"Stupid bug! You go squish now!!" - Homer Simpson

### #5Reedbeta

DevMaster Staff

• 5309 posts
• LocationSanta Clara, CA

Posted 11 April 2008 - 04:24 AM

Kenneth: that should be accounted for in the value returned from QueryPerformanceFrequency, no?
reedbeta.com - developer blog, OpenGL demos, and other projects

### #6Kenneth Gorking

Senior Member

• Members
• 939 posts

Posted 11 April 2008 - 05:15 AM

True, but I was thinking about synchronicity. If one subsystem is running twice as fast/slow as the others, couldn't timing anomalies occur?

Consider this:[INDENT]
Thread 1 (1.5Ghz) : Rendering, AI
Thread 2 (3.0Ghz) : Physics, Audio[/INDENT]
"Stupid bug! You go squish now!!" - Homer Simpson

### #7Reedbeta

DevMaster Staff

• 5309 posts
• LocationSanta Clara, CA

Posted 11 April 2008 - 05:45 AM

Oh, definitely, if they're running on different cores (with physically separate clocks) then even if the cores are at the same clock speed, timing anomalies WILL occur. That's what the code polyvertex linked to is trying to account for, by setting the thread affinity mask so that it always calls QPC on the same core.

I don't think you can have two threads on the same core running at different clock speeds...that wouldn't make much sense to me.
reedbeta.com - developer blog, OpenGL demos, and other projects

### #8polyvertex

Member

• Members
• 32 posts

Posted 11 April 2008 - 06:23 AM

You could even call SetThreadAffinityMask(threadHandle, 1) to always stick to the first core but, as you can see, OGRE developers are going further by calling GetProcessAffinityMask() (see the Timer::reset() method, line 84) to be fully compliant with current OS and hardware settings, which seems to be a good thing...

I have to say that since I changed my Windows Timer class to use those tricks (constant thread affinity masking and potential leaps compensating), I never had timing problems anymore...

### #9Kenneth Gorking

Senior Member

• Members
• 939 posts

Posted 11 April 2008 - 07:16 AM

Reedbeta said:

I don't think you can have two threads on the same core running at different clock speeds...that wouldn't make much sense to me.
It was supposed to say core 1/2, my bad :)
"Stupid bug! You go squish now!!" - Homer Simpson

### #10polyvertex

Member

• Members
• 32 posts

Posted 11 April 2008 - 09:01 AM

Wow, I just found this.
Does somebody know what is this "/invisible/src/" URL thingy ? :)

Reedbeta, why did you suggested to the OP to convert LARGE_INTEGER to floating point here ?

### #11Sol_HSA

Senior Member

• Members
• 510 posts
• LocationNowhere whenever

Posted 11 April 2008 - 10:57 AM

'invisible' seems to be one microsoft research project last updated in 2004..
http://iki.fi/sol - my schtuphh

### #12Reedbeta

DevMaster Staff

• 5309 posts
• LocationSanta Clara, CA

Posted 11 April 2008 - 08:26 PM

polyvertex said:

Reedbeta, why did you suggested to the OP to convert LARGE_INTEGER to floating point here ?

I was just thinking that it would be simpler and more convenient to work with times in floating point format rather than 64-bit integers. However, Nils said later in that thread that he thought this was a bad idea because the roundoff errors could become significant. So, the timer should internally keep the time as a LARGE_INTEGER but then convert it to float when calculating the timestep for each frame (assuming your physics and logic routines use floating-point time).
reedbeta.com - developer blog, OpenGL demos, and other projects

#### 1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users