Client bottoleneck issue

Recently I have found out that there’s a “bottleneck” like issue in my game:

As you can see the weapon is firing really slow and sounds are out of synchronization, the camera is also supposed to change it’s angle after I was being eliminated but it didn’t.

What are the possible reasons of this happening? My game uses one huge client code which manages everything and interacts with different modules.
I’m not sure is it related to the recent changes to my code, but I also found out that this only happen in this certain map which I added recently.
There are no errors in console nor any spikes in the performance stats.

2 Likes

Unless you’re using a ton of coroutines, it’s probably not a good idea to have a single giant script on the client handling everything.

I sort of use coroutines often, but the purpose of that is to make sure the script to run without getting stopped by errors or it’s performance wise?

So coroutines allow the processes inside the coroutine to share resources with the rest of the script while running almost simulataneously (not exactly though because it’s still a single thread), so if you have like 15 coroutines running a bunch of stuff all at the same time, the client’s resources will be split among all 15 of those coroutines, which could be the reason it is slowing down.

If I were you, I would split your giant script into a bunch of smaller ones, so it is easier to manage, and I’m sure you could get rid of some of the coroutines by doing this as well.

1 Like

Agreed. Bottlenecks are really hard to manage when all of a code base is in one place. My recent project is a way to force me to use module scripts and put my code everywhere, to avoid having to manage coroutines and threading. Module scripts are helpful in this case, which is another thing I’ve been pushing myself to use.

(Also I am a huge fan of your game, can’t wait till it’s out of beta!)

2 Likes

One thing I dislike module scripts on client and how easily it can be exploited. Values inside a module script can be easily changed by cheaters comparing it to one big script, the point of having a single big client script is to share variables within a script such that they can interact with each other.

Don’t get me wrong: I do use module scripts, but usually only for storing/ referencing data that are used for further more actions in the main script. I guess I’ll try to reduce the amount of coroutines.

I don’t see how having your values stored in module scripts makes them easier to exploit than on a script. An exploiter will be able to see everything stored on the client regardless of where on the client it is stored.

Also, are you telling me that your giant script on the client is not using remote functions, but actually is running and storing everything that a client should not have access to?

No, I understand that exploiter has access to everything to the client, but comparing modules to one big script, a cheater can easily mess up with the game with:

require(module).something = true

“Something” can be some client configs, such as settings, state configurations (whether the player is at menu?) etc. These client config values are hard to be protected by the server. Yes, I know that one big script can be exploited too, however from what I’ve known it’s way harder than just by a simple one-lined command.

My point above might not be valid to you, but it can’t deny the fact that I love accessing different variables in one big script without worrying whether the variable is being referenced or not. Yet you might say you can just spit into few scripts that do different jobs! (Such as one for framework, one for client datastore loader) But even if they are being spitted into 2 scripts, it’s still hard to access variables, you will never know when will you use the variable in script A while working on script B.

What I can really do to boost performance is to simplify stuff inside the big script, that’s it! So far I don’t see much a problem from using one big script. According to the console, the LuaHeap never goes up to 21 MB (I don’t know is that a valid judging factor though, at least 21 MB is reasonable? It hops between 16 to 20 most of the time.)

I admit that the problem mentioned in the OP is more or less related to the “one big script” concept, but later I found out it’s because I was doing some maths inside a stepped for ALL the players in the server (basically 60 * around 15 players = 900 calculations per second lol), I’m not sure is this the root cause of the bottleneck issue but it seems to better after I remove that part of the code.

OR it might be related to this FPS counter, I’ve moved it into another script to see whether the problem will be solved.

Are you firing remote events every second since your shooting every second?

It’s not that I don’t find anything valid or not, it’s simply that I’m trying to understand how your code operates without actually having the code in front of me.

But anyway, like you said just now with you finding out you were running 900 calculations per second inside of a stepped event, and how you moved your FPS counter to another script, I was pushing you towards splitting your script down into smaller chunks just so you could easily debug your code.

Basically my entire point here is that if you try to break apart and simplify your code (use module scripts for functions too, not just storing variables), you will have an easier time finding what is actually slowing it down.

If you’re really still worried that much about security, then just don’t store that info on the client and use remote events to keep track of it on the server, and only send it to the client when the client is able to request it.

Also, a side note: instead of coroutines to run things without errors stopping your code, look into pcall(), you can find it half way down on the Lua globals page.

Hes not wrong, If you split the script up into multiple sections, you can pin down where the majority of the script activity is going on, then optimize from there. You can always just remerge everything afterwards.

It’d be more appropriate to use the profiler here, if you know if it’s a script that is causing it and possibly which one is suspect.

1 Like

Way I see it, yes, it would be harder for an exploiter to read one large script, but at the same time, you’re impacting the readability yourself and causing the bottleneck issue. A determined exploiter will still be able to read the code, so it shouldn’t affect the outcome that much.

It is a pain, and there are honestly times where I hate having to switch to my module script to find the information I need to pass into a function. But it helps. Making documentation for functions in your module script does help, and will minimize the amount of difficulty you have managing module scripts.

It’s a small price to pay to not have to constantly think about coroutines and the general flow of different tasks throughout your script.