From e1f84a756eaffb0c4aba4334b93cd9906cc4a3a8 Mon Sep 17 00:00:00 2001 From: Lohikar Date: Sat, 2 Sep 2017 13:35:03 -0500 Subject: [PATCH] experimental caching performance tweaks (#3364) Changes the asset cache's on-connect cache to use a ticking subsystem instead of sleeps and timers to slowly send assets to clients. --- code/controllers/subsystems/assets.dm | 52 ++++++++++++++++++++++++--- code/modules/client/asset_cache.dm | 17 ++------- code/modules/client/client procs.dm | 5 ++- 3 files changed, 53 insertions(+), 21 deletions(-) diff --git a/code/controllers/subsystems/assets.dm b/code/controllers/subsystems/assets.dm index 06673355a66..7111f0738ee 100644 --- a/code/controllers/subsystems/assets.dm +++ b/code/controllers/subsystems/assets.dm @@ -1,20 +1,64 @@ - /var/datum/controller/subsystem/assets/SSassets /datum/controller/subsystem/assets name = "Assets" init_order = SS_INIT_MISC_FIRST - flags = SS_NO_FIRE + flags = SS_BACKGROUND | SS_FIRE_IN_LOBBY + wait = 1 var/list/cache = list() + var/list/target_clients = list() + var/list/currentrun /datum/controller/subsystem/assets/New() NEW_SS_GLOBAL(SSassets) +/datum/controller/subsystem/assets/stat_entry() + ..("C:[target_clients.len]") + /datum/controller/subsystem/assets/Initialize(timeofday) for(var/type in typesof(/datum/asset) - list(/datum/asset, /datum/asset/simple)) var/datum/asset/A = new type() A.register() + CHECK_TICK - for(var/client/C in global.clients) - addtimer(CALLBACK(GLOBAL_PROC, .proc/getFilesSlow, C, cache, FALSE), 10) + for (var/client/C in global.clients) + handle_connect(C) ..() + +/datum/controller/subsystem/assets/proc/handle_disconnect(client/C) + target_clients -= C + if (currentrun) + currentrun -= C + +/datum/controller/subsystem/assets/proc/handle_connect(client/C) + if (!C) + CRASH("Client is missing.") + + target_clients[C] = cache.Copy() + if (suspended) + wake() + +/datum/controller/subsystem/assets/fire(resumed = 0) + if (!resumed) + currentrun = target_clients.Copy() + + if (!target_clients.len) + suspend() + + while (currentrun.len) + var/client/C = currentrun[currentrun.len] + currentrun.len-- + + if (!C) + continue + + var/list/c_files = target_clients[C] + + if (!c_files.len) + target_clients -= C + else + send_asset(C, c_files[1], FALSE) + c_files.Cut(1, 2) + + if (MC_TICK_CHECK) + return diff --git a/code/modules/client/asset_cache.dm b/code/modules/client/asset_cache.dm index 1b9fe21661d..d4550557871 100644 --- a/code/modules/client/asset_cache.dm +++ b/code/modules/client/asset_cache.dm @@ -25,7 +25,7 @@ You can set verify to TRUE if you want send() to sleep until the client has the //This proc sends the asset to the client, but only if it needs it. //This proc blocks(sleeps) unless verify is set to false -/proc/send_asset(var/client/client, var/asset_name, var/verify = TRUE) +/proc/send_asset(client/client, asset_name, verify = TRUE) if(!istype(client)) if(ismob(client)) var/mob/M = client @@ -72,7 +72,7 @@ You can set verify to TRUE if you want send() to sleep until the client has the return 1 //This proc blocks(sleeps) unless verify is set to false -/proc/send_asset_list(var/client/client, var/list/asset_list, var/verify = TRUE) +/proc/send_asset_list(client/client, list/asset_list, verify = TRUE) if(!istype(client)) if(ismob(client)) var/mob/M = client @@ -122,20 +122,9 @@ You can set verify to TRUE if you want send() to sleep until the client has the return 1 -//This proc will download the files without clogging up the browse() queue, used for passively sending files on connection start. -//The proc calls procs that sleep for long times. -/proc/getFilesSlow(var/client/client, var/list/files, var/register_asset = TRUE) - for(var/file in files) - if (!client) - break - if (register_asset) - register_asset(file,files[file]) - send_asset(client,file) - sleep(0) //queuing calls like this too quickly can cause issues in some client versions - //This proc "registers" an asset, it adds it to the cache for further use, you cannot touch it from this point on or you'll fuck things up. //if it's an icon or something be careful, you'll have to copy it before further use. -/proc/register_asset(var/asset_name, var/asset) +/proc/register_asset(asset_name, asset) SSassets.cache[asset_name] = asset //These datums are used to populate the asset cache, the proc "register()" does this. diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index 236e5804eff..2f378566afe 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -380,6 +380,7 @@ admins -= src directory -= ckey clients -= src + SSassets.handle_disconnect(src) return ..() @@ -491,9 +492,7 @@ //send resources to the client. It's here in its own proc so we can move it around easiliy if need be /client/proc/send_resources() - spawn (10) //removing this spawn causes all clients to not get verbs. - //Precache the client with all other assets slowly, so as to not block other browse() calls - getFilesSlow(src, SSassets.cache, register_asset = FALSE) + SSassets.handle_connect(src) /mob/proc/MayRespawn() return 0