Sign in to follow this  
Evil Steve

XAudio2: GetPerformanceData() time in milliseconds?

Recommended Posts

Hi all,

What is the correct way to convert the performance data given by XAudio2's GetPerformanceData() function to actual time values?

Currently, I'm reading the CPU speed from the registry, which gives me 2814MHz, which is 2814000000 cycles / second.
When I call GetPerformanceData(), the TotalCyclesSinceLastQuery member is set to 1685086 (in this frame) - which works out at 0.0005988 seconds, or 0.5988ms.
However, I know that my game tick takes 66.66ms (Using other timer code, which I know works, and the game "looks" like it's running at 15 FPS), and I call GetPerformanceData once per game tick.
The AudioCyclesSinceLastQuery member is also set to 10639 - which works out at 0.00378ms - which seems awfully low (But might be correct, I'm only playing one 32KHz, 16-bit quad channel voice).

Am I failing at converting from cycles to milliseconds, or does XAudio's "CPU cycles" stuff not actually mean CPU cycles? Or am I only supposed to use the values to find out the fraction of CPU time used on audio?

Cheers,
Steve

P.S. Does anyone with access to Microsoft Code Center Premium know if the XAudio source code is available there? I had a look but didn't see anything, and the search function is useless...

Share this post


Link to post
Share on other sites
Well I'm going to take a shot in the dark at this. I know you've already taken a look at MSDN probably, but just to keep myself organized I'm going to reference everything I went over.

First I went to check out the definitions of AudioCyclesSinceLastQuery and TotalCyclesSinceLastQuery. One thing I found sort of ambiguous is the note on total cycles, "This only counts cycles on the CPU that XAudio2 is running on." I'm not totally familiar with XAudio2, but I'm pretty sure it employs the use of threading. Possibly the audio processing thread is on another core, thus the cycles being returned are the amount of time spent in asynchrouns function calls to XAudio2. I doubt this, but it is just something to think about.

Next I calculated theorectically how many bytes of your one voice should be consumed in 66.66 milliseconds:
32,000 Hz * 2 bytes * 4 (channels) = 256000 bytes/s * 0.06666 s = 17064.96 bytes processed in 66.66 ms.
Given that value, the audio cycles count doesn't seem too far off assuming that I'm pretty sure it will vary between frames depending on whether XAudio2 is ahead or behind in processing. (In your example above it would appear as though XAudio2 was ahead in processing, thus it took less time that frame to process the amount it needed to.)

As a last note, is the value returned by the registry the same as the value returned by QueryPerformanceFrequency?

Share this post


Link to post
Share on other sites
Quote:
Original post by Halifax2
Well I'm going to take a shot in the dark at this. I know you've already taken a look at MSDN probably, but just to keep myself organized I'm going to reference everything I went over.

First I went to check out the definitions of AudioCyclesSinceLastQuery and TotalCyclesSinceLastQuery. One thing I found sort of ambiguous is the note on total cycles, "This only counts cycles on the CPU that XAudio2 is running on." I'm not totally familiar with XAudio2, but I'm pretty sure it employs the use of threading. Possibly the audio processing thread is on another core, thus the cycles being returned are the amount of time spent in asynchrouns function calls to XAudio2. I doubt this, but it is just something to think about.

Next I calculated theorectically how many bytes of your one voice should be consumed in 66.66 milliseconds:
32,000 Hz * 2 bytes * 4 (channels) = 256000 bytes/s * 0.06666 s = 17064.96 bytes processed in 66.66 ms.
Given that value, the audio cycles count doesn't seem too far off assuming that I'm pretty sure it will vary between frames depending on whether XAudio2 is ahead or behind in processing. (In your example above it would appear as though XAudio2 was ahead in processing, thus it took less time that frame to process the amount it needed to.)

As a last note, is the value returned by the registry the same as the value returned by QueryPerformanceFrequency?
Hi, thanks for the reply.

QueryPerformanceFrequency gives the frequency of the high performance timer, which isn't nessecarily the CPU speed (It gives 40-odd MHz for QPF()).

The cycle count only being for the CPU core that XAudio runs on (It has an audio thread which runs, as you guessed) shouldn't make any difference really, and if AudioCyclesSinceLastQuery is 10639, then processing 17064 bytes in that many clock cycles still seems pretty low, given that XAudio is surely doing more than just copying data from one buffer to another? Maybe not I guess, but the TotalCyclesSinceLastQuery still seems particularly low...

Share this post


Link to post
Share on other sites
Hi Steve,

Only recently played with XAudio2 and I wanted to give those performance stats a shot at one point.

I set up a simple test (SlimDX) playing one voice, measuring time at a fixed 66 ms tick (artificially using sleep) with QPC, which I know works here. Turns out your approach works correctly on my system, assuming you are using e.g. HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\CentralProcessor\0\~MHz.

Comparing TotalCyclesSinceLastQuery and the measured delta time (ratio) gives me about a 2000 MHz "sample frequency", pretty stable each tick, a minor bias of about 1MHz. This value is closely returned by both said registry value (1999 MHz) and QPF (1,999,990,000 Hz).

Sad but true, I can't find anything conclusive in the docs yet what these "CPU" cycles actually mean or how the XAudio2 timing works internally either. Neither can I find a handy GetEngineCycleFrequency() or something. Source code would come in handy, but I can't help in this regard ... :/

Your numbers evaluate to (1685086 samples / 66.6 ms = ) 25 MHz approximately. Does that ring any bells ? Can you find that value somewhere, e.g. system or driver information ?

My emphasis here is on "stable". If it behaves the same way (across systems) then you can at least find out by measuring a couple of frames. Likely not the most accurate solution but at least a start. Then again: From the docs it's not clear to me if this approach is sane.

By the way: Calcing back AudioCyclesSinceLastQuery gives me about 1% or 0.5 ms which sounds not that far off for "the time spent" in an audio layer.

Hope that helps

[Edited by - unbird on December 10, 2010 10:59:32 AM]

Share this post


Link to post
Share on other sites
For future reference, the values returned apparently aren't CPU cycles at all, they're values from QueryPerformanceCounter() according to the Games For Windows team.

Hooray for documentation :P

Share this post


Link to post
Share on other sites
Quote:
Original post by Evil Steve
For future reference, the values returned apparently aren't CPU cycles at all, they're values from QueryPerformanceCounter() according to the Games For Windows team.

Hooray for documentation :P


Honestly I thought that might be the case. In the documentation for QPC they reference the return value as CPU cycles. But you're right, I dislike MSDN's ambiguity sometimes.

Share this post


Link to post
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

Sign in to follow this