Mtasa-blue: GTA sounds cause huge FPS drops but don't in SP

Created on 23 Aug 2019  Â·  16Comments  Â·  Source: multitheftauto/mtasa-blue

Is your feature request related to a problem? Please describe.
I just discovered that GTA sounds cause a huge FPS drop, thanks to being able to disable them with setWorldSoundEnabled. When I have peds shooting at me, I'd always get low FPS and I always thought it was something like the bullet effects but in fact doing:

for i=0, 44 do setWorldSoundEnabled ( i, false, true ) end

Completely eliminates the FPS drop and the FPS drop is not trivial. It was from ~100 to ~60 with 2 peds shooting at me with M4's. Doing resetWorldSounds() would make the FPS drop again.

Describe the solution you'd like
I've not idea if this is possible but is there some way that the sound system not cause such large FPS drops? And it's not just from shooting, '/showsound' is showing me a constant spam of about 10 sounds per second from players in the area but are so distant that none of the sounds are actually audio-able even at high volume and by disabling sounds my FPS would go from ~80 to ~100 so one solution maybe if any sounds where the volume would be so low the player can't hear them, that they'd be aborted which would at least help quite a bit.

Describe alternatives you've considered
I have tried cancelling sounds with:

addEventHandler("onClientWorldSound", root, function() cancelEvent() end)

To see if that would improve FPS, but it has no effect. So it must be some code before we get to onClientWorldSound that eats FPS. Could it be the reading from disk? If it is, well then the FPS hit would be way worse for other players because I'm using an SSD. Maybe it needs what ccw did for the CJ clothes, a cache of most commonly played sounds.

Because the FPS drop is so bad I will be adding settings so that players have certain spammy sounds disabled when their FPS drops below a certain range that they can adjust. I'm also going to find out what sounds are created most (I'll add the code to an example in onClientWorldSound) because there might be just a few sounds that are played so much they destroy FPS, like foot steps.

Additional context
I was just thinking, @saml1er found that the biggest FPS problem of all was something like "DX draw call state changes" but I'm guessing that test was done with no players running and driving around because must a debug build (and therefore no players making noises) be used for that analysis?

bug

Most helpful comment

I just tested this, i created 40 peds and ordered them to walk around. I got a loss of 15 fps (75 -> 60 fps) while the peds were walking with sound enabled.
Disabling Foot step sounds (World sounds 41, 1 - 5) completely eliminated any fps drop (Stable 75 fps). We always thought GTA Ped collisions were causing fps drop when many players were around - in fact the foot steps were causing the fps drop.

All 16 comments

Oh, another thing that we may add to the "eats fps" list.

  1. setElementData
    ̶2̶̶.̶̶ ̶̶p̶̶e̶̶d̶̶ ̶̶c̶̶o̶̶l̶̶l̶̶i̶̶s̶̶i̶̶o̶̶n̶̶s̶
  2. Too many draw calls
  3. Lua functions that are not stored as local variable (For whatever reason)
  4. Using dxDraw... a few dozen times
  5. GTA sounds

I just tested setElementData and the FPS impact of setting 10,000 element datas on myself was only 1 second. Though 10,000 times on an object freezes the game for 16 seconds. I really don't see how you can compare some trivial FPS drop from setElementData which you can easily avoid by not calling setElementData hundreds of times per second compared to FPS going from 250 to 141 just by firing the M4.

A script that disables gun fire sounds and plays it's own sounds is actually much better for FPS by handling onClientPlayerWeaponFire and aborting for any distant shooting / not playing the sound every bullet and I guess if playSound/3D would accept a string of the file instead of file path it'd be even more efficient unless playSound/3D already kind of does this by not loading from disk every time a small sound is played over and over.

We want 60 fps, this means we have 16 milliseconds time for a frame to complete.

I have tested it just now and setElementData does need the exact same time for objects that it needs for any other thing, maybe your 16s freeze was a rare issue (i need ~1400ms for 10000x)

But that means that i can use only 110x setElementData each frame before it needs more than 16ms that the frame needs to complete. Any other function can be called millions of times before that happens, and i have a very powerful machine. People with weaker PCs might run into problems with maybe 50-80x setElementData per frame and keep in mind that this happens without anything else running in the background.

Trust me, it is a problem and i am not saying your sound performance issue is not meaningful, in fact it seems to be even worse and i have not even noticed this problem yet. However, my server rarely goes beyond 45-50 fps anyway because of 30.000 lines of script that are running.

I guess if playSound/3D would accept a string of the file instead of file path it'd be even more efficient

Yes, it would be nice to be able to load "sound data" and manage that memory ourselves.

not loading from disk every time a small sound is played over and over.

An optimisation like this is done for the drawing, so I would assume they are also done for the sound functions. However, after a _very_ quick look, I can't find any code that does this for sounds.

I just tested this, i created 40 peds and ordered them to walk around. I got a loss of 15 fps (75 -> 60 fps) while the peds were walking with sound enabled.
Disabling Foot step sounds (World sounds 41, 1 - 5) completely eliminated any fps drop (Stable 75 fps). We always thought GTA Ped collisions were causing fps drop when many players were around - in fact the foot steps were causing the fps drop.

Backlogging this and marking it as a bug since it's 'unoptimised'

I forgot to mention that Sam1ler asked me to test in single player if firing the M4 makes FPS drop and it did not (and yes I did have FPS limiter disabled) so for some reason GTA sound playing is super inefficient in MTA but not GTA.

@Einheit-101 what about disabling the mentioned sounds but implementing the same exact sounds via playSound, I'll try that.

I did not try that yet but i will do that anyway for my next project, not because of performance, but because i want to create a footstep system that makes it easier to hear footsteps at a greater distance.

When r20460 (which adds #1234) is available as recommended client version this will hopefully be able to improve the performance of our sound scripts if we convert them to using fileOpen and playSound/3D with raw data on the sounds we're playing often. So yeah for foot steps you can use onClientPedStep with raw data in playSound3D and use setWorldSoundEnabled to disable default foot steps and hopefully the FPS drop from that test Einheit-101 did when the peds walk will be much lower.

playSound already caches afaik? And the new system might not be better as bass has to decode the sound every time you call playSound. We might have to replace that feature with a new "SoundData" element which you can pass to playSound.

@qaisjp you said this in an earlier comment:

An optimisation like this is done for the drawing, so I would assume they are also done for the sound functions. However, after a _very_ quick look, I can't find any code that does this for sounds.

lol

Btw, im pretty sure its because of this event, called OnClientWorldSound

With setEData i noticed that calling the event takes > 60% of time. Now, imagine us calling this event every tick a weapon fires.. 😅
Thats why disabling them, or playing in SP solves the FPS drop.

Does someone have a list of all foot step sound IDs that have to be disabled? I am now working on my custom footstep system.

Does someone have a list of all foot step sound IDs that have to be disabled? I am now working on my custom footstep system.

This works best for me (with a low impact on gameplay):

setWorldSoundEnabled(41, 1, false, true)
setWorldSoundEnabled(41, 2, false, true)
setWorldSoundEnabled(41, 3, false, true)
setWorldSoundEnabled(41, 4, false, true)
setWorldSoundEnabled(41, 5, false, true)
Was this page helpful?
0 / 5 - 0 ratings

Related issues

qaisjp picture qaisjp  Â·  4Comments

CrosRoad95 picture CrosRoad95  Â·  3Comments

PlatinMTA picture PlatinMTA  Â·  3Comments

rk-r picture rk-r  Â·  4Comments

ALw7sH picture ALw7sH  Â·  3Comments