Clients/Client2018/content/LuaPackages/RoactImpl/Instrumentation.lua

104 lines
3.0 KiB
Lua

--[[
An optional instrumentation layer that the reconciler calls into to record
various events.
Tracks a number of stats, including:
Recorded stats:
- Render count by component
- Update request count by component
- Actual update count by component
- shouldUpdate returned true count by component
- Time taken to run shouldUpdate
- Time taken to render by component
Derivable stats (for profiling manually or with a future tool):
- Average render time by component
- Percent of total render time by component
- Percent of time shouldUpdate returns true
- Average shouldUpdate time by component
- Percent of total shouldUpdate time by component
]]
local Instrumentation = {}
local componentStats = {}
--[[
Determines name of component from the given instance handle and returns a
stat object from the componentStats table, generating a new one if needed
]]
local function getStatEntry(handle)
local name
if handle and handle._element and handle._element.component then
name = tostring(handle._element.component)
else
warn("Component name not valid for " .. tostring(handle._key))
return nil
end
local entry = componentStats[name]
if not entry then
entry = {
-- update requests
updateReqCount = 0,
-- actual updates
didUpdateCount = 0,
-- time spent in shouldUpdate
shouldUpdateTime = 0,
-- number of renders
renderCount = 0,
-- total render time spent
renderTime = 0,
}
componentStats[name] = entry
end
return entry
end
--[[
Logs the time taken and resulting value of a Component's shouldUpdate function
]]
function Instrumentation.logShouldUpdate(handle, updateNeeded, shouldUpdateTime)
-- Grab or create associated entry in stats table
local statEntry = getStatEntry(handle)
if statEntry then
-- Increment the total number of times update was invoked
statEntry.updateReqCount = statEntry.updateReqCount + 1
-- Increment (when applicable) total number of times shouldUpdate returned true
statEntry.didUpdateCount = statEntry.didUpdateCount + (updateNeeded and 1 or 0)
-- Add time spent checking if an update is needed (in millis) to total time
statEntry.shouldUpdateTime = statEntry.shouldUpdateTime + shouldUpdateTime * 1000
end
end
--[[
Logs the time taken value of a Component's render function
]]
function Instrumentation.logRenderTime(handle, renderTime)
-- Grab or create associated entry in stats table
local statEntry = getStatEntry(handle)
if statEntry then
-- Increment total render count
statEntry.renderCount = statEntry.renderCount + 1
-- Add render time (in millis) to total rendering time
statEntry.renderTime = statEntry.renderTime + renderTime * 1000
end
end
--[[
Clears all the stats collected thus far. Useful for testing and for profiling in the future
]]
function Instrumentation.clearCollectedStats()
componentStats = {}
end
--[[
Returns all the stats collected thus far. Useful for testing and for profiling in the future
]]
function Instrumentation.getCollectedStats()
return componentStats
end
return Instrumentation