[Solved] Severe Performance Issue

Hello,

After some new sounds added, our game has a significant frame drop. After some investigation, I have found that setting event instance parameters every frame will cause frame time increase dramatically when multiple instances of the same event are present.
The frame time increase in my case is almost 30ms in FMOD Studio, and jumping up and down; this is too laggy even for my strategy game.

I have made 2 small programs to demonstrate this, one using FMOD EX and one FMOD Studio. They just init and prepare 20 instances of same looping event, enter the main loop. Every frame it sets parameters and sleeps a little. The time measure showed what I just said. On my computer the Studio is around [17000us to 29000us]. And EX takes no time.
I am setting them every frame because they change based on game state.

FMOD Studio Version:

do
{
.......
	FMODERRCHK( system->update() );

	for (int i=0;i<ARRAYSIZE(eventInstance);i++)
	{
		eventInstance[i]->setParameterValueByIndex(0, 0.5f);
		eventInstance[i]->setParameterValueByIndex(1, 0.0f);

		FMOD_3D_ATTRIBUTES attributes = { {0} };
		attributes.forward.z = 1.0f;
		attributes.up.y = 1.0f;
		eventInstance[i]->set3DAttributes(&attributes);
	}
.......
.......
	printf("FMOD Studio\n");
	printf("Frame time: %lld us\n", prevMaxFrameTime);

	Sleep(1);
		
} while (!GetAsyncKeyState(VK_ESCAPE));

FMOD EX Version:

do
{
	.......

	for (int i=0;i<ARRAYSIZE(testSubject);i++)
	{
		FMOD_VECTOR pos = {0,0,0};
		FMOD_VECTOR vel = {0,0,0};
		FMOD_VECTOR ori = {0,0,1};
		testSubject[i]->set3DAttributes(&pos, &vel, &ori);

		param1[i]->setValue(0.5f);
		param2[i]->setValue(0.0f);
	}

	ERRCHECK(result = eventsystem->update());

	.......

	printf("FMOD EX\n");
	printf("Frame time: %lld us\n", prevMaxFrameTime);

	Sleep(1);
} while (!GetAsyncKeyState(VK_ESCAPE));

If you comment out any setXXX in FMOD Studio version, it will be fine.

The events are basically the same. In fact, even if I use an empty event with no sound, the FMOD Studio version still lags. Am I missing something here?

This really makes me want to go back to the good old FMOD EX.

Visual Studio Project download link: https://dl.dropboxusercontent.com/u/219 … d_perf.zip

An update on this. I was using 1.3.3. After updating to 1.3.7 this issue gets somewhat better.
The test programs report maximum frame time during the last 10 frames. On 1.3.7, the chances of a long time frame(>17ms) is lower, but occurrence of those long frames it is still here.

I also tried measuring with QueryPerformanceCounter. This is more accurate.
It seems the long delays are multiples of 16ms + 1ms, in addition to small overheads such as 2us to 15us. For EX the time is like tens of microseconds(us).

Edit:
After increase the instance count to 80. (also increase MaxPlayback in EX). Ex runs around 130us while Studio runs around 39-49ms.

Edit2:
More info: also tested Studio with an empty event. Other effects disabled. Similar results.

OK I think I found a temporary solution to this. I need to use FMOD_STUDIO_INIT_SYNCHRONOUS_UPDATE when initializing.

This is how I found it:
After some assembly level debugging, I followed the execution into the fmodstudio.dll. I have found that there are EnterCriticalSection & LeaveCriticalSection calls in Studio::ParameterInstance::setValue and Studio::EventInstance::set3DAttributes. And in FMOD Designer API, I only see shorter assembly code and no CriticalSections.

At the same time the profiler shows the resource usage is low. And the lag seems not using up any much CPU. This makes me think the thread is suspended and waiting for the critical section. So I began to suspect this is the cause of the lag.

Some time later after the rest, I began to wonder if FMOD Studio offer a way to do the API calls in single threaded mode. This way those critical sections will make no sense and therefore they should be disabled. I began searching the documentation and found that FMOD_STUDIO_INIT_SYNCHRONOUS_UPDATE flag.

For drawbacks, it seems there are a few minor ones making glitches in rare cases. Overall, this works for me. I will continue more testing.

It sounds like you’re overflowing the async command buffer, especially with your 1ms sleep before setting all the parameters again. I don’t know if that’s indicative of your real workload, or just part of your test. Try increasing the async command buffer size.

From the docs:

Thanks for the reply Nick.

Increasing the size of command buffer works. I think I will also keep an eye on the usage by calling Studio::System::getBufferUsage