You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

662 lines
25 KiB

-- profiling support (WIP)
local Plater = _G.Plater
local FPSData = Plater.FPSData
local DF = _G.DetailsFramework
local C_Timer = _G.C_Timer
local debugprofilestop = debugprofilestop
local collectgarbage = collectgarbage
local loggedEvents = {}
local profStartTime = 0
local memStart = 0
local memEnd = 0
local profEndTime = 0
local profilingEnabled = false
local everyFrameLogSkipFirst = true
local PRT_INDENT = " "
-- trace gargbage
local garbageCalls = {}
local function traceGarbage(var)
if not profilingEnabled then return end
if var and var ~= "collect" then return end
local trace = debugstack(2)
local source, lineNum = trace:match("\"@([^\"]+)\"%]:(%d+)")
if not source then
-- Attempt to pull source out of "in function <file:line>" string
source, lineNum = trace:match("in function <([^:%[>]+):(%d+)>")
if not source then
-- Give up and record entire traceback
source = trace
lineNum = "(unhandled exception)"
end
end
print(var, source, lineNum)
if source then
garbageCalls[source .. ":" .. lineNum] = (garbageCalls[source .. ":" .. lineNum] or 0) + 1
end
end
hooksecurefunc("collectgarbage", traceGarbage)
-- helper
local function round(x)
if not x then return nil end
return (x + 0.5 - (x + 0.5) % 1)
end
local function roundTime(value)
if not value then return nil end
return round(value*100000)/100000
end
local function roundPercent(value)
if not value then return nil end
return round(value*1000)/1000
end
local function roundMem(value)
if not value then return nil end
return round(value*10)/10
end
local function getRoundMem(value)
if not value then return nil end
if value > 1000 then
return roundMem(value/1024) .. "MB"
else
return roundMem(value) .. "kb"
end
end
local function sumUpMemUsage(memValues)
local totMem = 0
local gcCount = 0
local lastMem
for _, val in pairs(memValues or {}) do
local curMem = (val - (lastMem or val))
if curMem < 0 then
curMem = 0
gcCount = gcCount + 1
end
totMem = totMem + curMem
lastMem = val
end
return totMem, gcCount
end
local function getFPSValuesFromTimes(times)
local values = {}
if not times then return values end
for _, ftime in pairs(times) do
tinsert(values, round(1000/ftime))
end
return values
end
local function getAverageTime(times)
local sum = 0;
if not times then return sum end
for _, v in pairs(times) do
sum = sum + v
end
return sum / #times
end
local function getModeTime(times, dec)
if not times then return 0, 0, 0 end
local tmpData = {}
for _, v in pairs(times or {}) do
v = round(v * (dec or 1000))/(dec or 1000)
tmpData[v] = (tmpData[v] or 0) + 1
end
local val, amount = 0, 0
for k, v in pairs(tmpData) do
if v > amount then
amount = v
val = k
end
end
return val, amount, #times
end
local function getMedianTime(times)
local med = 0
if times and (#times > 0) then
table.sort(times)
med = times[math.ceil(#times/2)]
end
return med
end
local function getMinMax(times)
local min, max = 9999999, 0
for _, v in pairs(times) do
if v < min then min = v end
if v > max then max = v end
end
return min, max
end
-- profiling
local function everyFrameEventLog()
if not profilingEnabled then
PlaterDBChr.perfEventLog = nil -- reset this.
return
end
C_Timer.After( 0, everyFrameEventLog )
if everyFrameLogSkipFirst then
everyFrameLogSkipFirst = false
end
local curTime = debugprofilestop()
tinsert(loggedEvents, {pType = "Game-Core", event = "Frame Tick", subType = "Frame Tick Internal", timestamp = curTime, startEvent = false, endEvent = false, isFrameTick = true, curFPS = FPSData.curFPS, curMem = collectgarbage("count")})
end
C_Timer.After( 0, everyFrameEventLog )
function Plater.StartLogPerformance()
end
function Plater.StartLogPerformanceCore()
end
local function StartLogPerformance(pType, event, subType)
if not profilingEnabled or not pType or not event or not subType then return end
local startTime = debugprofilestop()
tinsert(loggedEvents, {pType = pType, event = event, subType = subType, timestamp = startTime, startEvent = true, endEvent = false, curFPS = FPSData.curFPS, curMem = collectgarbage("count")})
end
function Plater.EndLogPerformance()
end
function Plater.EndLogPerformanceCore()
end
local function EndLogPerformance(pType, event, subType)
if not profilingEnabled or not pType or not event or not subType then return end
local stopTime = debugprofilestop()
tinsert(loggedEvents, {pType = pType, event = event, subType = subType, timestamp = stopTime, startEvent = false, endEvent = true, curFPS = FPSData.curFPS, curMem = collectgarbage("count")})
end
function Plater.EnableProfiling(core)
profilingEnabled = true
profStartTime = debugprofilestop()
profEndTime = nil
memEnd = nil
loggedEvents = {}
garbageCalls = {}
Plater.StartLogPerformance = StartLogPerformance
Plater.EndLogPerformance = EndLogPerformance
if core then
Plater.StartLogPerformanceCore = StartLogPerformance
Plater.EndLogPerformanceCore = EndLogPerformance
end
everyFrameLogSkipFirst = true
C_Timer.After( 0, everyFrameEventLog )
Plater:Msg("Plater started profiling.")
collectgarbage("restart")
collectgarbage("stop")
memStart = collectgarbage("count")
end
function Plater.DisableProfiling()
if not profilingEnabled then return end
memEnd = collectgarbage("count")
collectgarbage("restart")
profilingEnabled = false
profEndTime = debugprofilestop()
Plater.StartLogPerformance = function() end
Plater.EndLogPerformance = function() end
Plater.StartLogPerformanceCore = function() end
Plater.EndLogPerformanceCore = function() end
--Plater.DumpPerformance(true) -- for VDT mainly atm
Plater:Msg("Plater stopped profiling.")
if PlaterPerformanceProfilingResultPanel and PlaterPerformanceProfilingResultPanel:IsVisible() then
Plater.ShowPerfData()
end
end
local function getAdvancedPerfData()
local profData = {}
profData.data = {}
profData.fpsValues = {}
profData.fpsTimes = {}
profData.memValues = {}
profData.memFrameTicks = {}
local prevEventStack = {}
local prevEventForType = {}
--consolidate events
for _, logEntry in pairs(loggedEvents) do
--{pType, event, subType, timestamp, startEvent, endEvent, curFPS, curMem}
local curPTypeData = profData.data[logEntry.pType]
if not curPTypeData then
profData.data[logEntry.pType] = {}
profData.data[logEntry.pType].eventData = {}
curPTypeData = profData.data[logEntry.pType]
end
local curEventData = curPTypeData.eventData[logEntry.event]
if not curEventData then
curPTypeData.eventData[logEntry.event] = {}
curPTypeData.eventData[logEntry.event].subTypeData = {}
curPTypeData.eventData[logEntry.event].times = {}
curPTypeData.eventData[logEntry.event].fpsValues = {}
curPTypeData.eventData[logEntry.event].memValues = {}
curEventData = curPTypeData.eventData[logEntry.event]
end
local curSubTypeData = curEventData.subTypeData[logEntry.subType]
if not curSubTypeData then
curEventData.subTypeData[logEntry.subType] = {}
curEventData.subTypeData[logEntry.subType].times = {}
curEventData.subTypeData[logEntry.subType].fpsValues = {}
curEventData.subTypeData[logEntry.subType].memValues = {}
curSubTypeData = curEventData.subTypeData[logEntry.subType]
end
if logEntry.startEvent then
tinsert(prevEventStack, logEntry)
curEventData.startTime = logEntry.timestamp
curEventData.curMem = logEntry.curMem
if #prevEventStack == 1 then
curEventData.curStartTime = logEntry.timestamp
curEventData.curStartMem = logEntry.curMem
end
curSubTypeData.curStartTime = logEntry.timestamp
curSubTypeData.curStartMem = logEntry.curMem
curSubTypeData.curFPS = logEntry.curFPS
curSubTypeData.curMem = logEntry.curMem
tinsert(profData.fpsValues, logEntry.curFPS)
tinsert(profData.memValues, logEntry.curMem)
elseif logEntry.endEvent then
local prevLogEntry = tremove(prevEventStack)
curEventData.count = (curEventData.count or 0) + 1
local usedMem
local stopTime = logEntry.timestamp
local curSTime = (stopTime - prevLogEntry.timestamp)
local curETime
if #prevEventStack == 0 then
usedMem = logEntry.curMem - curEventData.curStartMem
if usedMem < 0 then usedMem = 0 end
curETime = (stopTime - curEventData.curStartTime)
profData.totalTimeInPlater = (profData.totalTimeInPlater or 0) + curETime
profData.totalMemInPlater = (profData.totalMemInPlater or 0) + usedMem
curEventData.totalTime = (curEventData.totalTime or 0) + curSTime
curEventData.totalMem = (curEventData.totalMem or 0) + usedMem
tinsert(curEventData.times, curETime)
curEventData.curStartTime = nil
curEventData.curStartMem = nil
else
usedMem = logEntry.curMem - curSubTypeData.curStartMem
if usedMem < 0 then usedMem = 0 end
curETime = (stopTime - curSubTypeData.curStartTime)
curEventData.subLogTime = (curEventData.subLogTime or 0) + curETime
curEventData.subLogMem = (curEventData.subLogMem or 0) + usedMem
curEventData.totalTime = (curEventData.totalTime or 0) + curETime
curEventData.totalMem = (curEventData.totalMem or 0) + usedMem
tinsert(curEventData.times, curETime)
end
curSubTypeData.curStartTime = nil
tinsert(curSubTypeData.times, curSTime)
-- add to event subType
curSubTypeData.totalTime = (curSubTypeData.totalTime or 0) + curSTime
curSubTypeData.count = (curSubTypeData.count or 0) + 1
curSubTypeData.totalMem = (curSubTypeData.totalMem or 0) + usedMem
-- min/max values
if (curSubTypeData.minTime or 9999999) > curSTime then
curSubTypeData.minTime = curSTime
end
if (curSubTypeData.maxTime or 0) < curSTime then
curSubTypeData.maxTime = curSTime
end
if (curEventData.minTime or 9999999) > curETime then
curEventData.minTime = curETime
end
if (curEventData.maxTime or 0) < curETime then
curEventData.maxTime = curETime
end
tinsert(profData.memValues, logEntry.curMem)
elseif logEntry.isFrameTick then
local key = "FrameTick_Internal"
local lastTime = prevEventForType[key] and prevEventForType[key].timestamp
if lastTime then -- ignore start to first frame
local curETime = logEntry.timestamp - lastTime
curEventData.subTypeData = {} -- don't want this
curEventData.count = (curEventData.count or 0) + 1
curEventData.totalTime = (curEventData.totalTime or 0) + curETime
curEventData.totalMem = (curEventData.totalMem or 0) + 0 -- don't count here
tinsert(curEventData.times, curETime)
tinsert(profData.fpsTimes, curETime)
tinsert(profData.memFrameTicks, logEntry.curMem)
if (curEventData.minTime or 9999999) > curETime then
curEventData.minTime = curETime
end
if (curEventData.maxTime or 0) < curETime then
curEventData.maxTime = curETime
end
end
prevEventForType[key] = logEntry
else
--single event (ping), no timeframe -> count from last event.
local key = (logEntry.pType or "") .. "-|-" .. (logEntry.event or "") .. "-|-" .. (logEntry.subType or "")
local lastTime = prevEventForType[key] and prevEventForType[key].timestamp or profStartTime
local curMem = logEntry.curMem - (prevEventForType[key] and prevEventForType[key].curMem or memStart)
local curETime = logEntry.timestamp - lastTime
curEventData.totalTime = (curEventData.totalTime or 0) + curETime
curEventData.count = (curEventData.count or 0) + 1
curEventData.totalMem = (curEventData.totalMem or 0) + curMem
curSubTypeData.totalTime = (curSubTypeData.totalTime or 0) + curETime
curSubTypeData.count = (curSubTypeData.count or 0) + 1
curSubTypeData.curFPS = logEntry.curFPS
curSubTypeData.totalMem = (curSubTypeData.totalMem or 0) + curMem
tinsert(curEventData.times, curETime)
tinsert(curSubTypeData.times, curETime)
-- min/max values
if (curSubTypeData.minTime or 9999999) > curETime then
curSubTypeData.minTime = curETime
end
if (curSubTypeData.maxTime or 0) < curETime then
curSubTypeData.maxTime = curETime
end
if (curEventData.minTime or 9999999) > curETime then
curEventData.minTime = curETime
end
if (curEventData.maxTime or 0) < curETime then
curEventData.maxTime = curETime
end
prevEventForType[key] = logEntry
end
end
if ViragDevTool_AddData then
--ViragDevTool_AddData(profData,"Plater Profiling TMP Data")
--ViragDevTool_AddData(prevEventStack,"Plater Profiling TMP Data - Stack")
end
if DevTool and DevTool.AddData then
--DevTool:AddData(profData,"Plater Profiling TMP Data")
--DevTool:AddData(prevEventStack,"Plater Profiling TMP Data - Stack")
end
local perfTable = {}
local printStr = ""
local sumTimePTypes = 0
local sumMemPTypes = 0
local sumExecPTypes = 0
local totalGlobalTime = (profEndTime or debugprofilestop()) - (profStartTime or debugprofilestop())
--local totalGlobalMem = (memEnd or collectgarbage("count")) - (memStart or collectgarbage("count"))
local totalGlobalMem, gcCount = sumUpMemUsage(profData.memValues)
--do sort
local dataKeys = {}
for k in pairs(profData.data) do table.insert(dataKeys, k) end
table.sort(dataKeys)
for _, dataKey in pairs(dataKeys) do
local pType, data = dataKey, profData.data[dataKey]
perfTable[pType] = {}
local pTypeTime = 0
local pTypeExec = 0
local pTypeSubLog = 0
local pTypeSubLogMem = 0
local printStrPType = ""
local pTypeMem = 0
--do sort
local eventKeys = {}
for k in pairs(data.eventData) do table.insert(eventKeys, k) end
table.sort(eventKeys)
for _, eventKey in pairs(eventKeys) do
local event, pData = eventKey, data.eventData[eventKey]
perfTable[pType][event] = {}
pData.count = pData.count or 0
local modeVal, modeAmount, modeTotal = getModeTime(pData.times)
local modeData = roundTime(modeVal).." ("..modeAmount.."/"..modeTotal..")"
perfTable[pType][event].total = "count: " .. pData.count .. " - total: " .. roundTime(pData.totalTime) .. "ms - (direct: " .. roundTime(pData.totalTime - (pData.subLogTime or 0)) .. "ms, sub-log: " .. roundTime(pData.subLogTime or 0) .. "ms)\n" .. "min/max/avg/med/mod (ms): " .. roundTime(pData.minTime) .. " / " .. roundTime(pData.maxTime) .. " / " .. roundTime(pData.totalTime / pData.count) .. " / " .. roundTime(getMedianTime(pData.times)) .. " / " .. modeData .. "\nmemory: " .. getRoundMem(pData.totalMem)
pTypeTime = pTypeTime + pData.totalTime
pTypeSubLog = pTypeSubLog + (pData.subLogTime or 0)
pTypeSubLogMem = pTypeSubLogMem + (pData.subLogMem or 0)
pTypeExec = pTypeExec + pData.count
pTypeMem = pTypeMem + pData.totalMem
printStrPType = printStrPType .. PRT_INDENT .. event .. ":" .. "\n" .. PRT_INDENT .. PRT_INDENT .. "Total:\n" .. PRT_INDENT .. PRT_INDENT .. PRT_INDENT .. string.gsub(perfTable[pType][event].total, "\n", "\n" .. PRT_INDENT .. PRT_INDENT .. PRT_INDENT) .. "\n\n"
perfTable[pType][event]._subTypeData = {}
local pTypeSufTime = 0
local pTypeSufMem = 0
local pTypeSufExec = 0
if pData.subTypeData and #pData.subTypeData > 0 then printStrPType = printStrPType .. PRT_INDENT .. PRT_INDENT .. "Sub-Events:" .. "\n" end
--do sort
local subTypeDataKeys = {}
for k in pairs(pData.subTypeData) do table.insert(subTypeDataKeys, k) end
table.sort(subTypeDataKeys)
for _, sufDataKey in pairs(subTypeDataKeys) do
local subType, sufData = sufDataKey, pData.subTypeData[sufDataKey]
if sufData.totalTime then -- sanity check for bad data
local modeVal, modeAmount, modeTotal = getModeTime(sufData.times)
local modeData = roundTime(modeVal).." ("..modeAmount.."/"..modeTotal..")"
perfTable[pType][event]._subTypeData[subType] = "count: " .. sufData.count .. " - total: " .. roundTime(sufData.totalTime) .. "ms\n" .. "min/max/avg/med/mod (ms): " .. roundTime(sufData.minTime) .. " / " .. roundTime(sufData.maxTime) .. " / " .. roundTime(sufData.totalTime / sufData.count) .. " / " .. roundTime(getMedianTime(sufData.times)) .. " / " .. modeData .. "\nmemory: " .. getRoundMem(sufData.totalMem)
pTypeSufTime = pTypeSufTime + sufData.totalTime
pTypeSufMem = pTypeSufMem + sufData.totalMem
pTypeSufExec = pTypeSufExec + sufData.count
printStrPType = printStrPType .. PRT_INDENT .. PRT_INDENT .. PRT_INDENT .. subType .. "\n"
printStrPType = printStrPType .. PRT_INDENT .. PRT_INDENT .. PRT_INDENT .. PRT_INDENT .. string.gsub(perfTable[pType][event]._subTypeData[subType], "\n", "\n" .. PRT_INDENT .. PRT_INDENT .. PRT_INDENT .. PRT_INDENT) .. "\n\n"
else
printStrPType = printStrPType .. PRT_INDENT .. PRT_INDENT .. PRT_INDENT .. subType .. " - ERROR - NO TOTAL LOGGED\n\n"
end
end
perfTable[pType][event].pTypeSufTime = pTypeSufTime
perfTable[pType][event].pTypeSufMem = pTypeSufMem
perfTable[pType][event].pTypeSufExec = pTypeSufExec
printStrPType = printStrPType .. "\n"
end
perfTable[pType].pTypeTime = pTypeTime
perfTable[pType].pTypeExec = pTypeExec
perfTable[pType].pTypeSubLog = pTypeSubLog
perfTable[pType].pTypeMem = pTypeMem
perfTable[pType].pTypeSubLogMem = pTypeSubLogMem
perfTable[pType].pTypeGlobalPercent = pTypeTime / totalGlobalTime * 100
perfTable[pType].pTypeGlobalPercentDirect = (pTypeTime - pTypeSubLog) / totalGlobalTime * 100
perfTable[pType].pTypeGlobalPercentSubLog = pTypeSubLog / totalGlobalTime * 100
perfTable[pType].pTypeGlobalMemPercent = pTypeMem / totalGlobalTime * 100
perfTable[pType].pTypeGlobalMemPercentDirect = (pTypeMem - pTypeSubLogMem) / totalGlobalTime * 100
perfTable[pType].pTypeGlobalMemPercentSubLog = pTypeMem / totalGlobalTime * 100
sumTimePTypes = sumTimePTypes + pTypeTime
sumExecPTypes = sumExecPTypes + pTypeExec
sumMemPTypes = sumMemPTypes + pTypeMem
printStr = printStr .. pType .. ":" .. "\n" .. PRT_INDENT .. "Total -> count: " .. pTypeExec .. " - time: " .. roundTime(pTypeTime) .. "ms (direct: " .. roundTime(pTypeTime - pTypeSubLog) .. "ms/" .. roundPercent(perfTable[pType].pTypeGlobalPercentDirect) .. "%, sub-log: " .. roundTime(pTypeSubLog) .. "ms/" .. roundPercent(perfTable[pType].pTypeGlobalPercentSubLog) .. "%) - memory: " .. getRoundMem(sumMemPTypes) .. "\n\n" .. printStrPType
printStr = printStr .. "\n"
end
local fpsValues = getFPSValuesFromTimes(profData.fpsTimes) --profData.fpsValues
local fpsAverage = getAverageTime(fpsValues)
local minFPS, maxFPS = getMinMax(fpsValues)
local medFPS = getMedianTime(fpsValues)
local modeVal, modeAmount, modeTotal = getModeTime(fpsValues, 10)
local modFPS = round(modeVal*10)/10 .." ("..modeAmount.."/"..modeTotal..")"
perfTable.timeInPlaterProfile = (profData.totalTimeInPlater or 0) --sumTimePTypes
perfTable.totalLoggedEvents = sumExecPTypes
perfTable.totalAveragePerEvent = perfTable.timeInPlaterProfile / sumExecPTypes
perfTable.percentGlobalInPlater = perfTable.timeInPlaterProfile / totalGlobalTime * 100
perfTable.memInPlaterProfile = (profData.totalMemInPlater or 0)
perfTable.totalAverageMemPerEvent = perfTable.memInPlaterProfile / sumExecPTypes
perfTable.percentGlobalMemInPlater = perfTable.memInPlaterProfile / totalGlobalMem * 100
local printStrHeader = ""
printStrHeader = printStrHeader .. "Plater profiling totals:\n"
printStrHeader = printStrHeader .. PRT_INDENT .. "Profiling time: " .. roundTime(totalGlobalTime / 100000)*100 .. "s" .. "\n"
printStrHeader = printStrHeader .. PRT_INDENT .. "Global Memory: " .. getRoundMem(totalGlobalMem) .. " (" .. gcCount .. " GCs)\n"
printStrHeader = printStrHeader .. PRT_INDENT .. "Time in Plater: " .. roundTime(perfTable.timeInPlaterProfile) .. "ms" .. "\n"
printStrHeader = printStrHeader .. PRT_INDENT .. "Memory in Plater: " .. getRoundMem(perfTable.memInPlaterProfile) .. "\n"
printStrHeader = printStrHeader .. PRT_INDENT .. "Logged events: " .. perfTable.totalLoggedEvents .. "\n"
printStrHeader = printStrHeader .. PRT_INDENT .. "Average runtimetime of event: " .. roundTime(perfTable.totalAveragePerEvent) .. "ms" .. "\n"
printStrHeader = printStrHeader .. PRT_INDENT .. "Average memory of event: " .. getRoundMem(perfTable.totalAverageMemPerEvent) .. "\n"
printStrHeader = printStrHeader .. PRT_INDENT .. "% of global time: " .. roundPercent(perfTable.percentGlobalInPlater) .. "%" .. "\n"
printStrHeader = printStrHeader .. PRT_INDENT .. "% of global memory: " .. roundPercent(perfTable.percentGlobalMemInPlater) .. "%" .. "\n"
printStrHeader = printStrHeader .. PRT_INDENT .. "FPS (min/max/avg/med/mod): " .. round(minFPS*10)/10 .. " / " .. round(maxFPS*10)/10 .. " / " .. round(fpsAverage*10)/10 .. " / " .. round(medFPS*10)/10 .. " / " .. modFPS .. "\n\n"
printStr = printStrHeader .. printStr
printStr = printStr .. "Plater Version: " .. Plater.GetVersionInfo()
local gcHeaderPrinted = false
for name, count in pairs(garbageCalls or {}) do
if not gcHeaderPrinted then
printStr = printStr .. "\n\n\nExplicit GCs triggered: \n"
gcHeaderPrinted = true
end
printStr = printStr .. PRT_INDENT .. "'" .. name .. "': " .. count .. "\n"
end
return perfTable, printStr
end
function Plater.DumpPerformance(noPrintOut)
local perfTable, printStr = getAdvancedPerfData()
if ViragDevTool_AddData then
ViragDevTool_AddData(perfTable,"Plater Profiling Data")
ViragDevTool_AddData(loggedEvents,"Plater Profiling - Logged-Events")
end
if DevTool and DevTool.AddData then
DevTool:AddData(perfTable,"Plater Profiling Data")
DevTool:AddData(loggedEvents,"Plater Profiling - Logged-Events")
end
if not noPrintOut then
print(printStr)
end
return perfTable, printStr
end
local function createResultsPanel()
local f = CreateFrame ("frame", "PlaterPerformanceProfilingResultPanel", UIParent, "BackdropTemplate")
f:SetSize (900, 700)
f:EnableMouse (true)
f:SetMovable (true)
f:RegisterForDrag ("LeftButton")
f:SetScript ("OnDragStart", function() f:StartMoving() end)
f:SetScript ("OnDragStop", function() f:StopMovingOrSizing() end)
f:SetScript ("OnMouseDown", function (self, button) if (button == "RightButton") then f.TextField:ClearFocus() f:Hide() end end)
f:SetFrameStrata ("DIALOG")
f:SetPoint ("center", UIParent, "center", 0, 0)
f:SetBackdrop ({edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true})
f:SetBackdropColor (0, 0, 0, 0.8)
f:SetBackdropBorderColor (0, 0, 0, 1)
tinsert (UISpecialFrames, "PlaterPerformanceProfilingResultPanel")
DF:CreateTitleBar (f, "Plater Performance Profiling")
DF:ApplyStandardBackdrop (f)
local luaeditor_backdrop_color = {.2, .2, .2, .5}
local luaeditor_border_color = {0, 0, 0, 1}
local textField = DF:NewSpecialLuaEditorEntry (f, 875, 670, "TextField", "$parentTextField", true, false)
textField.editbox:SetFontObject ("GameFontHighlight")
textField:SetPoint ("top", f, "top", -10, -25)
--textField.editbox:SetEnabled(false)
textField:SetBackdrop ({edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true})
textField:SetBackdropBorderColor (unpack (luaeditor_border_color))
textField:SetBackdropColor (unpack (luaeditor_backdrop_color))
DF:ReskinSlider (textField.scroll)
f.TextField = textField
f:Hide()
Plater.PlaterPerformanceProfilingResultPanel = f
end
function Plater.ShowPerfData()
local perfTable, printStr = getAdvancedPerfData()
if (not PlaterPerformanceProfilingResultPanel) then
createResultsPanel()
end
Plater.PlaterPerformanceProfilingResultPanel.TextField:SetText (printStr)
Plater.PlaterPerformanceProfilingResultPanel:Show()
end
function Plater.ShowPerfDataSpec()
local perfTable, printStr = getAdvancedPerfData()
if (not PlaterPerformanceProfilingResultPanel) then
createResultsPanel()
end
Plater.PlaterPerformanceProfilingResultPanel.TextField:SetText (printStr)
Plater.PlaterPerformanceProfilingResultPanel:Show()
end
function Plater.StoreEventLogData()
local eventLogData = {}
for _, event in pairs(loggedEvents) do
if event.startEvent then
tinsert(eventLogData, '\n {"ph":"B","name":"' .. event.pType .. " - " .. event.event .. " - " .. event.subType .. '","ts":' .. (event.timestamp * 1000) .. ',"pid":0}')
elseif event.endEvent then
tinsert(eventLogData, '\n {"ph":"E","name":"' .. event.pType .. " - " .. event.event .. " - " .. event.subType .. '","ts":' .. (event.timestamp * 1000) .. ',"pid":0}')
else
tinsert(eventLogData, '\n {"ph":"I","name":"vsync","ts":'..(event.timestamp * 1000)..',"pid":1}')
end
end
local eventLogStr = "[" .. table.concat(eventLogData, ",") .. "]"
PlaterDBChr.perfEventLog = eventLogStr
ReloadUI()
end