mtasa-blue icon indicating copy to clipboard operation
mtasa-blue copied to clipboard

GTA sounds cause huge FPS drops but don't in SP

Open ArranTuna opened this issue 6 years ago • 34 comments

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?

ArranTuna avatar Aug 23 '19 09:08 ArranTuna

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

Einheit-101 avatar Aug 24 '19 00:08 Einheit-101

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.

ArranTuna avatar Aug 24 '19 09:08 ArranTuna

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.

Einheit-101 avatar Aug 24 '19 10:08 Einheit-101

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.

qaisjp avatar Aug 24 '19 16:08 qaisjp

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.

Einheit-101 avatar Oct 01 '19 22:10 Einheit-101

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

qaisjp avatar Mar 15 '20 00:03 qaisjp

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.

ArranTuna avatar Mar 15 '20 09:03 ArranTuna

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

Haxardous avatar Mar 24 '20 10:03 Haxardous

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.

Einheit-101 avatar Mar 24 '20 10:03 Einheit-101

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.

ArranTuna avatar Mar 24 '20 12:03 ArranTuna

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 avatar Mar 24 '20 16:03 qaisjp

@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.

ArranTuna avatar Mar 24 '20 16:03 ArranTuna

lol

qaisjp avatar Mar 24 '20 16:03 qaisjp

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.

Pirulax avatar Jun 09 '20 11:06 Pirulax

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.

Einheit-101 avatar Jul 16 '20 22:07 Einheit-101

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)

Dutchman101 avatar Jul 17 '20 07:07 Dutchman101

@Pirulax says that this is caused by the event onClientWorldSound well I just did a find in files (on CIT's scripts) and that event is only used in 1 unimportant script so I was just thinking how about a function to just disable onClientWorldSound so that servers that don't rely on this event don't have to suffer major FPS drops for something they don't even use.

Could be a function like setClientSetting("disableOnClientWorldSound", true) it would be useful to have a function like this for future changes that would save adding more functions.

ArranTuna avatar Aug 17 '21 09:08 ArranTuna

I built MTA, tested the FPS drop, then disabled onClientWorldSound by blanking CClientGame::WorldSoundHandler (verified that the event was not being called any more) but the FPS drop is still the same so it's nothing to do with event system.

ArranTuna avatar Nov 15 '21 17:11 ArranTuna

I've tested 3 times, here are the results:

Normal with enabled all sounds:

2021-11-16 11:21:23 - gta_sa
Frames: 756 - Time: 14734ms - Avg: 51.310 - Min: 45 - Max: 56

Disabled all footstep sounds:

2021-11-16 11:21:44 - gta_sa
Frames: 980 - Time: 16563ms - Avg: 59.168 - Min: 55 - Max: 64

Cancelled via onClientWorldSound:

2021-11-16 11:23:26 - gta_sa
Frames: 1077 - Time: 17953ms - Avg: 59.990 - Min: 53 - Max: 67

Test code: https://pastebin.com/raw/qYDiPKgj

Xenius97 avatar Nov 16 '21 10:11 Xenius97

Did you resetWorldSounds() before testing the "Cancelled via onClientWorldSound"? Because I recall from the tests I did that cancelling the event had no performance improvement, the sound had to be disabled via setWorldSoundEnabled for there to be no loss of performance.

ArranTuna avatar Nov 16 '21 10:11 ArranTuna

I've re-enable all default sounds, didn't use resetWorldSounds.

Xenius97 avatar Nov 16 '21 11:11 Xenius97

After testing this PR: https://github.com/multitheftauto/mtasa-blue/pull/2133

I realised it might be able to find the performance loss for this but all of the sampling CrosRoad95 added are in the deathmatch project and loads of audio code is in the Game SA project and I couldn't figure out how to call CPerformanceRecorder::Sample sample("name") from Game SA I tried stuff like WhatToPutHere->GetPerformanceRecorder()->Sample("name") I could never get the first part to be valid, I checked many Game SA files to see if there are any calls to deathmatch and couldn't find any is there no method setup for that?

ArranTuna avatar Nov 24 '21 09:11 ArranTuna

I did a little research and it looks like the problem is with framerate. The higher the FPS limit, the greater the FPS drops.

Here are the results of my tests:

FPS Limit: 74 Sound off: 74 FPS Sound on: 65 FPS

FPS Limit: 100 Sound off: 96 FPS Sound on: 61 FPS

It would be useful for someone to check an identical scenario in singleplayer using some mods or something.

for i = 1, 10 do
    local x, y, z = 1440.1682128906 + (i * 5), 1795.4040527344, 10.8203125
    local ped = createPed(0, x, y, z)

    givePedWeapon(ped, 30, 500, true)
    setPedControlState(ped, "aim", true)
    setPedControlState(ped, "fire", true)
end

There is a small chance that the problem is with MTA, since MTA doesn't do anything much with the audio other than grab it from GTA SA

FileEX avatar Jul 17 '24 16:07 FileEX

There is a small chance that the problem is with MTA, since MTA doesn't do anything much with the audio other than grab it from GTA SA

In a comment I made here in 2021: "Pirulax says that this is caused by the event onClientWorldSound"

It would be useful for someone to check an identical scenario in singleplayer using some mods or something.

You don't even need to use mods, just disable frame rate limit, have something like fraps showing FPS, fire the M4, the FPS in SP does not drop at all from that, but on MTA it does.

ArranTuna avatar Jul 17 '24 16:07 ArranTuna

There is a small chance that the problem is with MTA, since MTA doesn't do anything much with the audio other than grab it from GTA SA

In a comment I made here in 2021: "Pirulax says that this is caused by the event onClientWorldSound"

It would be useful for someone to check an identical scenario in singleplayer using some mods or something.

You don't even need to use mods, just disable frame rate limit, have something like fraps showing FPS, fire the M4, the FPS in SP does not drop at all from that, but on MTA it does.

What you described is not entirely reliable. In MTA, we observe FPS drops when several peds shoot at the same time, not when we shoot.

When I shoot alone in MTA, I don't have any FPS drops, but I see them when 10 NPCs are shooting image

FileEX avatar Jul 17 '24 16:07 FileEX

In a comment I made here in 2021: "Pirulax says that this is caused by the event onClientWorldSound"

From what you wrote earlier

I built MTA, tested the FPS drop, then disabled onClientWorldSound by blanking CClientGame::WorldSoundHandler (verified that the event was not being called any more) but the FPS drop is still the same so it's nothing to do with event system.

It turns out that the cause is not the onClientWorldSound event. I decided to check it myself by disabling the event at the source, i.e. editing the hook code, and there are still FPS drops, so the event has nothing to do with it

FileEX avatar Jul 17 '24 16:07 FileEX

Some research results: Function call at 0x4D9888 eats a lot FPS. By default i have 300-350 FPS, after disabling this call i have 450-500 FPS. Second performance drops caused by effects/render. When i look at weapon, i have 130-230 FPS (0x4D9888 call is disabled)

Repro resource: sound.zip

TheNormalnij avatar Jul 30 '24 22:07 TheNormalnij

Nice @TheNormalnij, here is more research from FileEX (as posted in dev discord):

Untitled

Fixing this would be huge for MTA

Dutchman101 avatar Jul 30 '24 22:07 Dutchman101

Some research results: Function call at 0x4D9888 eats a lot FPS. By default i have 300-350 FPS, after disabling this call i have 450-500 FPS. Second performance drops caused by effects/render. When i look at weapon, i have 130-230 FPS (0x4D9888 call is disabled)

Repro resource: sound.zip

Is it possible to disable rendering of default weapons? Like a new (toggle) function, since lots of people use e.g pAttach for their servers - but weapon is hidden, e.g by replacing model or setting absurdly low LOD distance. Given that performance boost (and secondly way to easily hide them) i think it would be good idea.

sacr1ficez avatar Jul 31 '24 04:07 sacr1ficez

Yes, it is possible to disable weapon object rendering and weapon processing (shooting, aiming, fx effects), but this is not the subject of this issue. Probably GTA was simply made with one player in mind, not a multiplayer where many sounds are played at the same time or many fx effects

FileEX avatar Jul 31 '24 10:07 FileEX