ID:2743380
 
(See the best response by Shadowkaroth.)
I have currently run into a bit of an issue where large battles between players start to lag clientside, likely due to the amount of things being drawn on the screen. For each player, there are 12 bodyparts, and each bodypart has its own 32x32 sprite that can be added or removed in cases of dismemberment. On top of that, the clothing has its own 32x32 icons for each item worn and there are a lot of clothing slots. Blood sprites are also a thing and are 32x32 as well, and there are generally a lot of blood sprites. Bullets also exist and have transform() calls frequently called on it to simulate bullet movement.

The project is intended to run at 60fps with a view range of 10. I know that this goes well beyond what Lummox intended for the game to be used but it's actually very doable if clientside lag was cut down by something like 15 to 20 percent.

So far I've down the following "optimizations":
- Reduce the view range from 11 to 10.
- Limit how many blood sprites can exist on a tile at once.
- Disable rendering of clothing if its under other clothing.
- Disable rendering of limbs and blood if it's under other clothing.
- I've implemented an icon redundancy system for turfs with special terrain.
- I've used the flags LONG_GLIDE | PIXEL_SCALE | TILE_BOUND | KEEP_TOGETHER for 95% of objects.


My graphics card is a Nvidia GTX 1070 so it isn't an issue of performance. I really don't want to do things like reduce the view range any further or make the intended clientside FPS 30 or something like that.

Would have to see how you handle loops, any code to show us that you feel would help?
In response to Kozuma3
Kozuma3 wrote:
Would have to see how you handle loops, any code to show us that you feel would help?

There is no serverside lag, thankfully, but I will answer the question anyways.


Loops are "tick checked" where a lot of intensive loops have a special define put into them where the code is slowed down until there are resources available.

#define CHECK_TICK(limit,max_delays) \
if(limit && world.tick_usage > limit) { \
var/safety_count=0; \
while(world.tick_usage > limit && (max_delays <= safety_count || !max_delays)) {\
safety_count++; \
sleep(TICK_LAG * (world.tick_usage/limit)); \
}\
}


limit is the maximum CPU usage allowed for the proc to run, and max_delays is how many times it can sleep for TICK_LAG (1 / the server's tickrate) multiplied by how much it's going over the limit.
Are you using vis_contents or overlays for the clothing/bodyparts?

[edit] I ask because having many objects within the visual_contents and having multiple objects doing such being displayed on the map in a single area can generate some "lag" on the client's fps.

When 515 adds GetFlatIcon() instead of it having to process all of your vis_contents and such you could simply cache the "4?" directions and use 4 images.
Best response
I believe KEEP_TOGETHER is intensive and should refrain from using it on too many objects.

If there was some magic bullet to solve this issue. We all would know it right now. But it sounds like for the most part you understand what things 'cause your latency issues and never tried to correct it as best as you can.

Speaking of bullets.. Why do your bullets need transformed to "simulate bullet movement" What do you need to simulate on an arrow type projectile? Other than say for angular directions.
KEEP_TOGETHER is going to work against you in cases where you don't need it. For your players and NPCs it's probably important, but for anything like blood stains, etc., not so much.

However, the renderer will help you out and effectively removes the flag from cases where an object has no overlays at all, so those situations won't cause the same performance drop.

Basically therefore you want to look for cases where KT is used where it isn't needed, for objects that do use overlays. For instance, if you're not using filters or alpha, it's usually not going to be an issue for the overlays to render separately.
In response to Shadowkaroth
Shadowkaroth wrote:
I believe KEEP_TOGETHER is intensive and should refrain from using it on too many objects.

If there was some magic bullet to solve this issue. We all would know it right now. But it sounds like for the most part you understand what things 'cause your latency issues and never tried to correct it as best as you can.

Speaking of bullets.. Why do your bullets need transformed to "simulate bullet movement" What do you need to simulate on an arrow type projectile? Other than say for angular directions.

Lummox JR wrote:
KEEP_TOGETHER is going to work against you in cases where you don't need it. For your players and NPCs it's probably important, but for anything like blood stains, etc., not so much.

However, the renderer will help you out and effectively removes the flag from cases where an object has no overlays at all, so those situations won't cause the same performance drop.

Basically therefore you want to look for cases where KT is used where it isn't needed, for objects that do use overlays. For instance, if you're not using filters or alpha, it's usually not going to be an issue for the overlays to render separately.

Removing KEEP_TOGETHER from /atom/ actually helped a TON. I thought that KEEP_TOGETHER would be less intensive because it drew everything as just one thing that needed to be drawn, but that was an incorrect assumption.
In response to Kozuma3
Kozuma3 wrote:
Are you using vis_contents or overlays for the clothing/bodyparts?

[edit] I ask because having many objects within the visual_contents and having multiple objects doing such being displayed on the map in a single area can generate some "lag" on the client's fps.

When 515 adds GetFlatIcon() instead of it having to process all of your vis_contents and such you could simply cache the "4?" directions and use 4 images.


Overlays. People keep telling me to use vis_contents but that would involve making a completely new system which I might do down the road if it's less intensive.
What KT is actually doing, is rendering everything attached to the object to an offscreen surface, and then rendering that offscreen surface onto the main surface when it finishes rendering its children.

This is graphically intense and should only be used when you absolutely need KT.

The magic bullet to making BYOND performant is to do the least work possible to achieve the desired result. This can be counter-intuitive, because sometimes what seems like the least work possible is actually putting quite a lot of work on the engine. Understanding how the engine actually works is critical to finding the lowest work solution to any given problem. This means reading documentation, testing things to see if your ideas hold water, and picking the brain of anyone you can.