ID:1479769
 
I'm trying to optimize my game but I'm pretty sure one big reason for "lag" is not having enough bandwidth. There is no way that I know of to profile the bandwidth usage in the game (Like with the cpu profiler)

Does anyone know what sort of things use the most bandwidth? Would rapidly changing variables (for example a variables that gains +1 every sleep(1)) cause a lot of signals to be sent and use a lot of bandwidth? Or is most of the bandwidth used by something I haven't thought of?

Thanks
The reason I think it lags due to lack of bandwidth is because world.cpu averages at about 30% and people will be lagging for no apparent reason still.

My game can handle 90 players before world.cpu reaches 55% on our most powerful server yet players will still lag despite lowish world.cpu.
The only things communicated to players are appearances. Basically unless a proc or var changes something the client can physically see, such as layer, alpha, icon_state, position, dir, etc, it doesn't cost bandwidth.
Then where are the clients getting all their updated variable values from? The server has to be sending it. Like each time the server increases "health" by +1 it would have to update all clients on the new value.

It could be called a design flaw, but I think my game does about 1000 combined changes to variables per second, whether it's health, power, whatever else
CPU usage is one thing, but with that many players you must be pretty high for physical memory as well.
The only thing that is communicated over the network are appearance and location changes.

The only variables that contribute to network traffic are:

icon
icon_state
dir
step_x
step_y
pixel_x
pixel_y
pixel_z
overlays
underlays
color
alpha
invisibility
layer
loc
transform

I might have missed one or two, but any variable you define won't be communicated across the network at all unless an interface update or an output() forces that data to be sent to the client in some sort of a message.

Now, there's one thing to look out for. If you are changing turfs, or initializing a huge number of objects, that's going to trigger network communication. You should be careful of changing turfs because any client currently looking at that turf will be sent their entire viewport.


To keep network communication down, make sure your pixel_x and pixel_y values are kept under around icon_size*4. When you exceed this, it generates extra communication. Also make sure your viewport is capped to a reasonable size. A viewport of 100x50 is just too big to have a lot of players moving around the map all at once, or changing turfs a lot.

I really doubt you are running into bandwidth issues, and are just misinterpreting something else as "lag".

Also, there is a network profiler, and you can monitor how much network usage individual applications are using from your computer's task manager. So you should know without a doubt what your bandwidth usage is.
In response to Balzack
Balzack wrote:
CPU usage is one thing, but with that many players you must be pretty high for physical memory as well.

Ram? Yea we are. Surprisingly high. But nowhere near the limits of the server.

In response to Ter13
Ter13 wrote:
The only thing that is communicated over the network are appearance and location changes.

The only variables that contribute to network traffic are:

icon
icon_state
dir
step_x
step_y
pixel_x
pixel_y
pixel_z
overlays
underlays
color
alpha
invisibility
layer
loc
transform

I might have missed one or two, but any variable you define won't be communicated across the network at all unless an interface update or an output() forces that data to be sent to the client in some sort of a message.

Now, there's one thing to look out for. If you are changing turfs, or initializing a huge number of objects, that's going to trigger network communication. You should be careful of changing turfs because any client currently looking at that turf will be sent their entire viewport.


To keep network communication down, make sure your pixel_x and pixel_y values are kept under around icon_size*4. When you exceed this, it generates extra communication. Also make sure your viewport is capped to a reasonable size. A viewport of 100x50 is just too big to have a lot of players moving around the map all at once, or changing turfs a lot.

I really doubt you are running into bandwidth issues, and are just misinterpreting something else as "lag".

Also, there is a network profiler, and you can monitor how much network usage individual applications are using from your computer's task manager. So you should know without a doubt what your bandwidth usage is.

That makes sense, thanks. So the only reason any player variables are being communicated over the network is because I am displaying them in the tabs to the player. This will help me a lot thanks.

Wow why would BYOND resend the entire viewport if 1 turf changes in their vicinity? I always thought BYOND only sent map updates to the clients with turfs that were changed from their initial type only, and that the other turfs that are still of their initial value were probably just loaded client side from the map file and not sent across the network.

I'm not claiming to know what I'm talking about but when I made this networked 3d game in Unity3d that is how it worked, the entire terrain was loaded client side from the game data, and only changes to the terrain were sent from the server to the client, the server would not have to resend the entire terrain data just because 1 thing changed. Explosions caused craters in the terrain mesh, and also change the texture to dirt at the crater. All I had to do was send the position and size of the crater, the rest was generated client side.

Regardless this helps a lot
Wow why would BYOND resend the entire viewport if 1 turf changes in their vicinity? I always thought BYOND only sent map updates to the clients with turfs that were changed from their initial type only, and that the other turfs that are still of their initial value were probably just loaded client side from the map file and not sent across the network.

BYOND is basically a graphical telnet client with some advanced features.

Back in the 80s and early 90s, all distributed applications pretty much had simplistic terminal clients and complicated server code that did all the logic for each connected client.

The way that you wrote your game in Unity, was sensible to modern sensibilities. BYOND just makes programming a lot easier from a client perspective because you don't have to manage client-side and server-side code.

The way that you are suggesting it should work is reasonable for most applications, but not all. Hence, the networking model stays where it is right now, because we can't predict what the client will actually need, map-wise.

Lummox has mentioned fixing this by making it so that BYOND will only send individual updates to viewed tiles when required, but I haven't seen word of this in a long time.

That makes sense, thanks. So the only reason any player variables are being communicated over the network is because I am displaying them in the tabs to the player. This will help me a lot thanks.

Not really. You aren't sending the variables. You are sending text, or appearance information over the network.

Stat() is a function that runs once every few ticks that tells the client to update a particular panel. It sends all the updates in text or appearance format.

The << directive takes data and sends it to the client, where the client knows how to deal with it automatically.

You aren't actually communicating the variables, just the output.
Cool. I've been told a few times that bandwidth is probably not why my game lags, and that networked games don't require as much bandwidth as people think. But the lag is coming from somewhere, and it isn't from world.cpu. But if it isn't bandwidth I am out of ideas for now.

But maybe for my game it IS bandwidth, due to a design flaw I just don't realize, there are constant changes to those networked variables you mentioned due to (as just one example of many) this "Who" tab that players have in my game, that displays the mobs of ALL players online. So while a player is looking at that tab many of those variables you mentioned are having to be communicated constantly because they can see all the icon/overlay/pixel/dir/etc changes of everyone all at once.
No, those variables aren't being communicated constantly.

But if you are worried about a statpanel updating constantly, there's a little-known feature that most people have been using wrong since the beginning that will save you some bandwidth:

Stat()
if(statpanel("Who"))
for(var/mob/m in onlineplayers)
stat(m)
if(statpanel("Stats"))
//update stats here.


Checking if() against a statpanel that's just given a named value, will not add anything to the statpanel, and as such, won't send any data across the network when stat() is run.

statpanel() will return 1 or 0 depending if the player is looking at it. I never see people use this feature, so I'm pretty sure I'm one of a handful of people who even knows it exists.


As for other things, you might check to see if you are indeed running into a CPU issue anyway by checking the CPU usage of the world from the task manager rather than from within BYOND. I think you might find that this is indeed a CPU issue.
Yep I actually do use if(statpanel()) in all statpanel code. Someone showed me that trick here a few years ago, probably you, who knows. Thanks.

But even so mob/Stat() is using the 2nd most cpu in the profiler right below mob/Move(). I also use sleep(3) at the bottom of Stat() to slow it down a bit. And if client.inactivity exceeds 1800 then Stat() will just sleep(15) then return before it even displays any tabs.

Yea maybe. I'll try to check that out.
Also, I use sleep() a lot. It is probably the most used built-in proc in my game. And I think maybe it uses a ton of CPU, yet doesn't appear in the cpu profiler.

But if I make my own sleep() proc which is just:
proc/Sleep(t=0)
sleep(t)

That will appear in the cpu profiler, and it will be the #1 most cpu consuming thing by far, like 20x more than the 2nd highest thing.
sleep() doesn't really burn up CPU. It just puts things off in the scheduler.

It might add some overhead, but you aren't going to see the overhead it causes in the profiler, because what little it does cause is going to be in the scheduler itself, which is not tracked.

Bad design is probably what eats most of your CPU, to be honest. Using for(v in X) unnecessarily, etc. Most peoples' games rely on shoestring code and bad practices, and could benefit from a more polymorphic, event-oriented approach.
Could anyone tell me why my custom sleep proc appears to burn 20x more cpu than the next highest thing on the cpu profiler then please?

I made that custom sleep proc, then used CTRL+H to replace all sleep()'s with Sleep()'s in my game to test it out.
Which kind of CPU are we talking here?

I tried this on another project and all I saw it using up was Real Time, which is ... what you'd expect, as the procedure starts, then goes to sleep for the time specified, before waking up, and completing.

Real Time is basically the 'wall clock time' something takes to complete, as opposed to any representation of how long it spent actually doing processing on the CPU. Procedures or verbs that have very long running loops with sleep() inside of them for example, would expect to see very high Real Time, even though they might not actually use much CPU time.
The most important thing to look at is self CPU. That's how much processing the proc itself took up. If you see a helper proc using a lot, find something with high total CPU and you've likely found what's calling that helper.
Well ... so so. If your general CPU use is very happy but your players are complaining of lag when doing some actions, looking at Real Time is a good way to help debug where errant sleeps have crept in.

Much the same with cumulative vs average displays. Each thing lets you splice the data a different way, and so tells you a different bit of the story.
Any changes to turf or area appearances will cause insane network usage, accumulated over a tick, this means if you spread out turf changes and do say, one per tick, the network usage may become absymal depending on your FPS