Files
Bubberstation/code/__DEFINES/time.dm
Kylerace 77c2b7f50c Biddle Verbs: Queues the Most Expensive Verbs for the Next Tick if the Server Is Overloaded (#65589)
This pr goes through: /client/Click(), /client/Topic(), /mob/living/verb/resist(), /mob/verb/quick_equip(), /mob/verb/examinate(), and /mob/verb/mode() and makes them queue their functionality to a subsystem to execute in the next tick if the server is overloaded. To do this a new subsystem is made to handle most verbs called SSverb_manager, if the server is overloaded the verb queues itself in the subsystem and returns, then near the start of the next tick that verb is resumed with the provided callback. The verbs are called directly after SSinput, and the subsystem does not yield until its queue is completely finished.

The exception are clicks from player input since they are extremely important for the feeling of responsiveness. I considered not queuing them but theyre too expensive not to, suffering from a death of a thousand cuts performance wise from many many things in the process adding up. Instead clicks are executed at the very start of the next tick, as the first action that SSinput completes, before player movement is processed even.

A few months ago, before I died I was trying to figure out why games at midpop (40-50 people) had non zero and consistent time dilation without maptick being consistently above 28% (which is when the MC stops yielding for maptick if its overloaded). I found it out, started working on this pr, then promptly died. luckily im a bit less dead now

the current MC has a problem: the cost of verbs is completely and totally invisible to it, it cannot account for them. Why is this bad? because verbs are the last thing to execute in the tick, after the MC and SendMaps have finished executing.
tick diagram2
If the MC is overloaded and uses 100% of the time it allots itself this means that if SendMaps uses the amount its expected to take, verbs have at most 2% of the tick to execute in before they are overtiming and thus delaying the start of the next tick. This is bad, and im 99% sure this is the majority of our overtime.

Take Click() for example. Click isnt listed as a verb but since its called as a result of client commands its executed at the end of the tick like other verbs. in this random 80 pop sybil round profile i had saved on my computer sybil 80 pop (2).txt /client/Click() has an overtime of only 1.8 seconds, which isnt that bad. however it has a self cpu of 2.5 seconds meaning 1.8/2.5 = 72% of its time is overtiming, and it also is calling 80.2 seconds worth of total cpu, which means that more than 57.7 seconds of overtime is attributed to just /client/Click() executing at the very end of a tick. the reason why this isnt obvious is just because the verbs themselves typically dont have high enough self cpu to get high enough on the rankings of overtiming procs to be noticed, all of their overtime is distributed among a ton of procs they call in the chain.

Since i cant guarantee the MC resumes at the very start of the next tick due to other sleeping procs almost always resuming first: I time the duration between clicks being queued up for the next tick and when theyre actually executed. if it exceeds 20 milliseconds of added latency (less than one tenth the average human reaction time) clicks will execute immediately instead of queuing, this should make instances where a player can notice the added latency a vanishingly small minority of cases. still, this should be tm'd
2022-07-31 14:56:18 -07:00

163 lines
3.4 KiB
Plaintext

///number of deciseconds in a day
#define MIDNIGHT_ROLLOVER 864000
///displays the current time into the round, with a lot of extra code just there for ensuring it looks okay after an entire day passes
#define ROUND_TIME ( "[world.time - SSticker.round_start_time > MIDNIGHT_ROLLOVER ? "[round((world.time - SSticker.round_start_time)/MIDNIGHT_ROLLOVER)]:[worldtime2text()]" : worldtime2text()]" )
#define JANUARY 1
#define FEBRUARY 2
#define MARCH 3
#define APRIL 4
#define MAY 5
#define JUNE 6
#define JULY 7
#define AUGUST 8
#define SEPTEMBER 9
#define OCTOBER 10
#define NOVEMBER 11
#define DECEMBER 12
//Select holiday names -- If you test for a holiday in the code, make the holiday's name a define and test for that instead
#define NEW_YEAR "New Year"
#define VALENTINES "Valentine's Day"
#define APRIL_FOOLS "April Fool's Day"
#define EASTER "Easter"
#define HALLOWEEN "Halloween"
#define CHRISTMAS "Christmas"
#define FESTIVE_SEASON "Festive Season"
#define GARBAGEDAY "Garbage Day"
#define MONKEYDAY "Monkey Day"
#define PRIDE_WEEK "Pride Week"
#define MOTH_WEEK "Moth Week"
/*
Days of the week to make it easier to reference them.
When using time2text(), please use "DDD" to find the weekday. Refrain from using "Day"
*/
#define MONDAY "Mon"
#define TUESDAY "Tue"
#define WEDNESDAY "Wed"
#define THURSDAY "Thu"
#define FRIDAY "Fri"
#define SATURDAY "Sat"
#define SUNDAY "Sun"
#define MILLISECONDS *0.01
#define DECISECONDS *1 //the base unit all of these defines are scaled by, because byond uses that as a unit of measurement for some fucking reason
#define SECONDS *10
#define MINUTES SECONDS*60
#define HOURS MINUTES*60
#define TICKS *world.tick_lag
#define DS2TICKS(DS) ((DS)/world.tick_lag)
#define TICKS2DS(T) ((T) TICKS)
#define MS2DS(T) ((T) MILLISECONDS)
#define DS2MS(T) ((T) * 100)
/*Timezones*/
/// Line Islands Time
#define TIMEZONE_LINT 14
// Chatham Daylight Time
#define TIMEZONE_CHADT 13.75
/// Tokelau Time
#define TIMEZONE_TKT 13
/// Tonga Time
#define TIMEZONE_TOT 13
/// New Zealand Daylight Time
#define TIMEZONE_NZDT 13
/// New Zealand Standard Time
#define TIMEZONE_NZST 12
/// Norfolk Time
#define TIMEZONE_NFT 11
/// Lord Howe Standard Time
#define TIMEZONE_LHST 10.5
/// Australian Eastern Standard Time
#define TIMEZONE_AEST 10
/// Australian Central Standard Time
#define TIMEZONE_ACST 9.5
/// Australian Central Western Standard Time
#define TIMEZONE_ACWST 8.75
/// Australian Western Standard Time
#define TIMEZONE_AWST 8
/// Christmas Island Time
#define TIMEZONE_CXT 7
/// Cocos Islands Time
#define TIMEZONE_CCT 6.5
/// Central European Summer Time
#define TIMEZONE_CEST 2
/// Coordinated Universal Time
#define TIMEZONE_UTC 0
/// Eastern Daylight Time
#define TIMEZONE_EDT -4
/// Eastern Standard Time
#define TIMEZONE_EST -5
/// Central Daylight Time
#define TIMEZONE_CDT -5
/// Central Standard Time
#define TIMEZONE_CST -6
/// Mountain Daylight Time
#define TIMEZONE_MDT -6
/// Mountain Standard Time
#define TIMEZONE_MST -7
/// Pacific Daylight Time
#define TIMEZONE_PDT -7
/// Pacific Standard Time
#define TIMEZONE_PST -8
/// Alaska Daylight Time
#define TIMEZONE_AKDT -8
/// Alaska Standard Time
#define TIMEZONE_AKST -9
/// Hawaii-Aleutian Daylight Time
#define TIMEZONE_HDT -9
/// Hawaii Standard Time
#define TIMEZONE_HST -10
/// Cook Island Time
#define TIMEZONE_CKT -10
/// Niue Time
#define TIMEZONE_NUT -11
/// Anywhere on Earth
#define TIMEZONE_ANYWHERE_ON_EARTH -12