Merge pull request #2232 from SinTwo/scheduler

510 scheduler
This commit is contained in:
EmperorJon
2016-08-08 10:36:36 +01:00
committed by GitHub
48 changed files with 206 additions and 238 deletions

View File

@@ -1,19 +0,0 @@
/**
* _stubs.dm
*
* This file contains constructs that the process scheduler expects to exist
* in a standard ss13 fork.
*/
/**
* logTheThing
*
* In goonstation, this proc writes a message to either the world log or diary.
*
* Blame Keelin.
*/
/proc/logTheThing(type, source, target, text, diaryType)
if(diaryType)
log_debug("Diary: \[[diaryType]:[type]] [text]")
else
log_debug("Log: \[[type]] [text]")

View File

@@ -69,10 +69,10 @@
* recordkeeping vars
*/
// Records the time (1/10s timeofday) at which the process last finished sleeping
// Records the time (1/10s timeoftick) at which the process last finished sleeping
var/tmp/last_slept = 0
// Records the time (1/10s timeofday) at which the process last began running
// Records the time (1/10s timeofgame) at which the process last began running
var/tmp/run_start = 0
// Records the number of times this process has been killed and restarted
@@ -106,12 +106,8 @@
last_object = null
/datum/controller/process/proc/started()
var/timeofhour = TimeOfHour
// Initialize last_slept so we can know when to sleep
last_slept = timeofhour
// Initialize run_start so we can detect hung processes.
run_start = timeofhour
run_start = TimeOfGame
// Initialize defer count
cpu_defer_count = 0
@@ -163,18 +159,13 @@
setStatus(PROCESS_STATUS_HUNG)
/datum/controller/process/proc/handleHung()
var/timeofhour = TimeOfHour
var/datum/lastObj = last_object
var/lastObjType = "null"
if(istype(lastObj))
lastObjType = lastObj.type
// If timeofhour has rolled over, then we need to adjust.
if (timeofhour < run_start)
run_start -= 36000
var/msg = "[name] process hung at tick #[ticks]. Process was unresponsive for [(timeofhour - run_start) / 10] seconds and was restarted. Last task: [last_task]. Last Object Type: [lastObjType]"
logTheThing("debug", null, null, msg)
logTheThing("diary", null, null, msg, "debug")
var/msg = "[name] process hung at tick #[ticks]. Process was unresponsive for [(TimeOfGame - run_start) / 10] seconds and was restarted. Last task: [last_task]. Last Object Type: [lastObjType]"
log_debug(msg)
message_admins(msg)
main.restartProcess(src.name)
@@ -182,8 +173,8 @@
/datum/controller/process/proc/kill()
if (!killed)
var/msg = "[name] process was killed at tick #[ticks]."
logTheThing("debug", null, null, msg)
logTheThing("diary", null, null, msg, "debug")
log_debug(msg)
message_admins(msg)
//finished()
// Allow inheritors to clean up if needed
@@ -208,17 +199,12 @@
if (main.getCurrentTickElapsedTime() > main.timeAllowance)
sleep(world.tick_lag)
cpu_defer_count++
last_slept = TimeOfHour
last_slept = 0
else
var/timeofhour = TimeOfHour
// If timeofhour has rolled over, then we need to adjust.
if (timeofhour < last_slept)
last_slept -= 36000
if (timeofhour > last_slept + sleep_interval)
if (TimeOfTick > last_slept + sleep_interval)
// If we haven't slept in sleep_interval deciseconds, sleep to allow other work to proceed.
sleep(0)
last_slept = TimeOfHour
last_slept = TimeOfTick
/datum/controller/process/proc/update()
// Clear delta
@@ -239,10 +225,7 @@
/datum/controller/process/proc/getElapsedTime()
var/timeofhour = TimeOfHour
if (timeofhour < run_start)
return timeofhour - (run_start - 36000)
return timeofhour - run_start
return TimeOfGame - run_start
/datum/controller/process/proc/tickDetail()
return
@@ -343,6 +326,11 @@
stat("[name]", "T#[getTicks()] | AR [averageRunTime] | LR [lastRunTime] | HR [highestRunTime] | D [cpu_defer_count]")
/datum/controller/process/proc/catchException(var/exception/e, var/thrower)
if(istype(e)) // Real runtimes go to the real error handler
// There are two newlines here, because handling desc sucks
e.desc = " Caught by process: [name]\n\n" + e.desc
world.Error(e, e_src = thrower)
return
var/etext = "[e]"
var/eid = "[e]" // Exception ID, for tracking repeated exceptions
var/ptext = "" // "processing..." text, for what was being processed (if known)
@@ -369,4 +357,4 @@
/datum/controller/process/proc/catchBadType(var/datum/caught)
if(isnull(caught) || !istype(caught) || !isnull(caught.gcDestroyed))
return // Only bother with types we can identify and that don't belong
catchException("Type [caught.type] does not belong in process' queue")
catchException("Type [caught.type] does not belong in process' queue")

View File

@@ -43,8 +43,6 @@ var/global/datum/controller/processScheduler/processScheduler
var/tmp/currentTick = 0
var/tmp/currentTickStart = 0
var/tmp/timeAllowance = 0
var/tmp/cpuAverage = 0
@@ -247,7 +245,7 @@ var/global/datum/controller/processScheduler/processScheduler
/datum/controller/processScheduler/proc/recordStart(var/datum/controller/process/process, var/time = null)
if (isnull(time))
time = TimeOfHour
time = TimeOfGame
last_queued[process] = world.time
last_start[process] = time
else
@@ -256,11 +254,7 @@ var/global/datum/controller/processScheduler/processScheduler
/datum/controller/processScheduler/proc/recordEnd(var/datum/controller/process/process, var/time = null)
if (isnull(time))
time = TimeOfHour
// If world.timeofday has rolled over, then we need to adjust.
if (time < last_start[process])
last_start[process] -= 36000
time = TimeOfGame
var/lastRunTime = time - last_start[process]
@@ -349,29 +343,23 @@ var/global/datum/controller/processScheduler/processScheduler
updateCurrentTickData()
return 0
else
return TimeOfHour - currentTickStart
return TimeOfTick
/datum/controller/processScheduler/proc/updateCurrentTickData()
if (world.time > currentTick)
// New tick!
currentTick = world.time
currentTickStart = TimeOfHour
updateTimeAllowance()
cpuAverage = (world.cpu + cpuAverage + cpuAverage) / 3
/datum/controller/processScheduler/proc/updateTimeAllowance()
// Time allowance goes down linearly with world.cpu.
var/tmp/error = cpuAverage - 100
var/tmp/timeAllowanceDelta = sign(error) * -0.5 * world.tick_lag * max(0, 0.001 * abs(error))
var/tmp/timeAllowanceDelta = SIMPLE_SIGN(error) * -0.5 * world.tick_lag * max(0, 0.001 * abs(error))
//timeAllowance = world.tick_lag * min(1, 0.5 * ((200/max(1,cpuAverage)) - 1))
timeAllowance = min(timeAllowanceMax, max(0, timeAllowance + timeAllowanceDelta))
/datum/controller/processScheduler/proc/sign(var/x)
if (x == 0)
return 1
return x / abs(x)
/datum/controller/processScheduler/proc/statProcesses()
if(!isRunning)
stat("Processes", "Scheduler not running")
@@ -379,4 +367,7 @@ var/global/datum/controller/processScheduler/processScheduler
stat("Processes", "[processes.len] (R [running.len] / Q [queued.len] / I [idle.len])")
stat(null, "[round(cpuAverage, 0.1)] CPU, [round(timeAllowance, 0.1)/10] TA")
for(var/datum/controller/process/p in processes)
p.statProcess()
p.statProcess()
/datum/controller/processScheduler/proc/getProcess(var/process_name)
return nameToProcessMap[process_name]

View File

@@ -1,56 +0,0 @@
(function ($) {
function setRef(theRef) {
ref = theRef;
}
function jax(action, data) {
if (typeof data === 'undefined')
data = {};
var params = [];
for (var k in data) {
if (data.hasOwnProperty(k)) {
params.push(encodeURIComponent(k) + '=' + encodeURIComponent(data[k]));
}
}
var newLoc = '?src=' + ref + ';action=' + action + ';' + params.join(';');
window.location = newLoc;
}
function requestRefresh(e) {
jax("refresh", null);
}
function handleRefresh(processTable) {
$('#processTable').html(processTable);
initProcessTableButtons();
}
function requestKill(e) {
var button = $(e.currentTarget);
jax("kill", {name: button.data("process-name")});
}
function requestEnable(e) {
var button = $(e.currentTarget);
jax("enable", {name: button.data("process-name")});
}
function requestDisable(e) {
var button = $(e.currentTarget);
jax("disable", {name: button.data("process-name")});
}
function initProcessTableButtons() {
$(".kill-btn").on("click", requestKill);
$(".enable-btn").on("click", requestEnable);
$(".disable-btn").on("click", requestDisable);
}
window.setRef = setRef;
window.handleRefresh = handleRefresh;
$(function() {
initProcessTableButtons();
$('#btn-refresh').on("click", requestRefresh);
});
}(jQuery));