Server API

This commit is contained in:
FPtje 2016-05-01 17:27:26 +02:00
parent 91e989539a
commit e98a3e60e0

View File

@ -12,6 +12,19 @@ util.AddNetworkString("FProfile_fullModelUpdate")
util.AddNetworkString("FProfile_focusUpdate")
util.AddNetworkString("FProfile_unsubscribe")
--[[-------------------------------------------------------------------------
Simplified version of the model
Contains only what the server needs to know
---------------------------------------------------------------------------]]
local model =
{
focusObj = nil, -- the function currently in focus
sessionStart = nil, -- When the last profiling session was started
recordTime = 0, -- Total time spent on the last full profiling session
bottlenecks = {}, -- The list of bottleneck functions
topLagSpikes = {}, -- Top of lagging functions
subscribers = RecipientFilter(), -- The players that get updates of the profiler model
}
--[[-------------------------------------------------------------------------
Helper function: receive a net message
@ -27,20 +40,97 @@ local function receive(msg, f)
end)
end
--[[-------------------------------------------------------------------------
Helper function:
Write generic row data to a net message
---------------------------------------------------------------------------]]
local function writeRowData(row)
net.WriteString(tostring(row.func))
net.WriteString(row.info.short_src)
net.WriteUInt(row.info.linedefined, 16)
net.WriteUInt(row.info.lastlinedefined, 16)
end
--[[-------------------------------------------------------------------------
Simplified version of the model
Contains only what the server needs to know
Helper function:
Send the bottlenecks to the client
Only sends the things displayed
---------------------------------------------------------------------------]]
local model =
{
focusObj = nil, -- the function currently in focus
sessionStart = nil, -- When the last profiling session was started
recordTime = 0, -- Total time spent on the last full profiling session
bottlenecks = {}, -- The list of bottleneck functions
topLagSpikes = {}, -- Top of lagging functions
subscribers = RecipientFilter(), -- The players that get updates of the profiler model
}
local function writeBottleNecks()
net.WriteUInt(#model.bottlenecks, 16)
for i, row in ipairs(model.bottlenecks) do
writeRowData(row)
net.WriteUInt(#row.names, 8)
for j, name in ipairs(row.names) do
net.WriteString(name.name)
net.WriteString(name.namewhat)
end
net.WriteUInt(row.total_called, 32)
net.WriteDouble(row.total_time)
net.WriteDouble(row.average_time)
end
end
--[[-------------------------------------------------------------------------
Helper function:
Sends the top n functions
---------------------------------------------------------------------------]]
local function writeTopN()
local count = #model.topLagSpikes
-- All top N f
for i = count, 0, -1 do
if model.topLagSpikes and model.topLagSpikes[i] and model.topLagSpikes[i].info then break end -- Entry exists
count = i
end
net.WriteUInt(count, 8)
for i = 1, count do
local row = model.topLagSpikes[i]
if not row.info then break end
writeRowData(row)
net.WriteString(row.info.name or "")
net.WriteString(row.info.namewhat or "")
net.WriteDouble(row.runtime)
end
end
-- Start profiling
local function startProfiling()
model.sessionStart = CurTime()
FProfiler.Internal.start(model.focusObj)
net.Start("FProfile_startProfiling")
net.WriteDouble(model.recordTime)
net.WriteDouble(model.sessionStart)
net.Send(model.subscribers:GetPlayers())
end
-- Stop profiling
local function stopProfiling()
FProfiler.Internal.stop()
model.recordTime = model.recordTime + CurTime() - (model.sessionStart or 0)
model.sessionStart = nil
model.bottlenecks = FProfiler.Internal.getAggregatedResults(100)
model.topLagSpikes = FProfiler.Internal.getMostExpensiveSingleCalls()
net.Start("FProfile_stopProfiling")
net.WriteDouble(model.recordTime)
writeBottleNecks()
writeTopN()
net.Send(model.subscribers:GetPlayers())
end
--[[-------------------------------------------------------------------------
@ -75,88 +165,15 @@ receive("FProfile_startProfiling", function(_, ply)
model.recordTime = 0
end
model.sessionStart = CurTime()
FProfiler.Internal.start(model.focusObj)
net.Start("FProfile_startProfiling")
net.WriteDouble(model.recordTime)
net.WriteDouble(model.sessionStart)
net.Send(model.subscribers:GetPlayers())
startProfiling()
end)
-- Write generic row data to a net message
local function writeRowData(row)
net.WriteString(tostring(row.func))
net.WriteString(row.info.short_src)
net.WriteUInt(row.info.linedefined, 16)
net.WriteUInt(row.info.lastlinedefined, 16)
end
-- Send the bottlenecks to the client
-- Only sends the things displayed
local function writeBottleNecks()
net.WriteUInt(#model.bottlenecks, 16)
for i, row in ipairs(model.bottlenecks) do
writeRowData(row)
net.WriteUInt(#row.names, 8)
for j, name in ipairs(row.names) do
net.WriteString(name.name)
net.WriteString(name.namewhat)
end
net.WriteUInt(row.total_called, 32)
net.WriteDouble(row.total_time)
net.WriteDouble(row.average_time)
end
end
-- Sends the top n functions
local function writeTopN()
local count = #model.topLagSpikes
-- All top N f
for i = count, 0, -1 do
if model.topLagSpikes and model.topLagSpikes[i] and model.topLagSpikes[i].info then break end -- Entry exists
count = i
end
net.WriteUInt(count, 8)
for i = 1, count do
local row = model.topLagSpikes[i]
if not row.info then break end
writeRowData(row)
net.WriteString(row.info.name or "")
net.WriteString(row.info.namewhat or "")
net.WriteDouble(row.runtime)
end
end
--[[-------------------------------------------------------------------------
Receive a stop profiling signal
---------------------------------------------------------------------------]]
receive("FProfile_stopProfiling", function(_, ply)
FProfiler.Internal.stop()
model.recordTime = model.recordTime + CurTime() - (model.sessionStart or 0)
model.sessionStart = nil
model.bottlenecks = FProfiler.Internal.getAggregatedResults(100)
model.topLagSpikes = FProfiler.Internal.getMostExpensiveSingleCalls()
net.Start("FProfile_stopProfiling")
net.WriteDouble(model.recordTime)
writeBottleNecks()
writeTopN()
net.Send(model.subscribers:GetPlayers())
stopProfiling()
end)
@ -247,3 +264,29 @@ Unsubscribe from the updates of the profiler
receive("FProfile_unsubscribe", function(_, ply)
model.subscribers:RemovePlayer(ply)
end)
--[[-------------------------------------------------------------------------
API function: start profiling
---------------------------------------------------------------------------]]
function FProfiler.start(focus)
FProfiler.Internal.reset()
model.recordTime = 0
model.focusObj = focus
startProfiling()
end
--[[-------------------------------------------------------------------------
API function: stop profiling
---------------------------------------------------------------------------]]
function FProfiler.stop()
stopProfiling()
end
--[[-------------------------------------------------------------------------
API function: continue profiling
---------------------------------------------------------------------------]]
function FProfiler.continueProfiling()
startProfiling()
end