vanilla-wow-addons – Rev 1

Subversion Repositories:
Rev:
local L = AceLibrary("AceLocale-2.0"):new("FuBar_PerformanceFu")
local Tablet = AceLibrary("Tablet-2.0")
local Abacus = AceLibrary("Abacus-2.0")
local Crayon = AceLibrary("Crayon-2.0")

PerformanceFu = AceLibrary("AceAddon-2.0"):new("FuBarPlugin-2.0", "AceConsole-2.0", "AceEvent-2.0", "AceDB-2.0")

PerformanceFu.version = "2.0" .. string.sub("$Revision: 7559 $", 12, -3)
PerformanceFu.date = string.sub("$Date: 2006-08-09 22:43:29 -1000 (Wed, 09 Aug 2006) $", 8, 17)
PerformanceFu.hasIcon = true

local string_format = string.format
local table_concat = table.concat
local table_insert = table.insert
local table_setn = table.setn

PerformanceFu:RegisterDB("PerformanceFuDB")
PerformanceFu:RegisterDefaults("profile", {
        showFramerate = true,
        showLatency = true,
        showMemory = true,
        showRate = true,
        warnGC = false,
})

function PerformanceFu:IsShowingFramerate()
        return self.db.profile.showFramerate
end

function PerformanceFu:ToggleShowingFramerate()
        self.db.profile.showFramerate = not self.db.profile.showFramerate
        self:Update()
end

function PerformanceFu:IsShowingLatency()
        return self.db.profile.showLatency
end

function PerformanceFu:ToggleShowingLatency()
        self.db.profile.showLatency = not self.db.profile.showLatency
        self:Update()
end

function PerformanceFu:IsShowingRate()
        return self.db.profile.showRate
end

function PerformanceFu:ToggleShowingRate()
        self.db.profile.showRate = not self.db.profile.showRate
        self:Update()
end

function PerformanceFu:IsShowingMemory()
        return self.db.profile.showMemory
end

function PerformanceFu:ToggleShowingMemory()
        self.db.profile.showMemory = not self.db.profile.showMemory
        self:Update()
end

function PerformanceFu:IsWarningOnGC()
        return self.db.profile.warnGC
end

function PerformanceFu:ToggleWarningOnGC()
        self.db.profile.warnGC = not self.db.profile.warnGC
end

local beeps5 = 0
local beeps15 = 0
local beeps30 = 0
local beeps60 = 0
local beeps180 = 0
local beeps600 = 0

local initialMemory, gcThreshold, currentMemory
local mem1, mem2, mem3, mem4, mem5, mem6, mem7, mem8, mem9, mem10
local timeSinceLastUpdate
local justEntered
local gcTime

function PerformanceFu:OnEnable()
        initialMemory, gcThreshold = gcinfo()
        currentMemory = initialMemory
        mem1 = currentMemory
        mem2 = currentMemory
        mem3 = currentMemory
        mem4 = currentMemory
        mem5 = currentMemory
        mem6 = currentMemory
        mem7 = currentMemory
        mem8 = currentMemory
        mem9 = currentMemory
        mem10 = currentMemory
        timeSinceLastUpdate = 0
        gcTime = time()
        justEntered = true
        self:ScheduleRepeatingEvent(self.OnUpdate, 1, self)
end

local options = {
        type = 'group',
        args = {
                framerate = {
                        type = 'toggle',
                        name = L"Show framerate",
                        desc = L"Toggle whether to framerate",
                        get = "IsShowingFramerate",
                        set = "ToggleShowingFramerate",
                },
                latency = {
                        type = 'toggle',
                        name = L"Show latency",
                        desc = L"Toggle whether to latency (lag)",
                        get = "IsShowingLatency",
                        set = "ToggleShowingLatency",
                },
                memory = {
                        type = 'toggle',
                        name = L"Show memory usage",
                        desc = L"Toggle whether to show current memory usage",
                        get = "IsShowingMemory",
                        set = "ToggleShowingMemory",
                },
                rate = {
                        type = 'toggle',
                        name = L"Show rate of increasing memory usage",
                        desc = L"Toggle whether to show increasing rate of memory",
                        get = "IsShowingRate",
                        set = "ToggleShowingRate",
                },
                warn = {
                        type = 'toggle',
                        name = L"Warn on garbage collection",
                        desc = L"Toggle whether to warn on an upcoming garbage collection",
                        get = "IsWarningOnGC",
                        set = "ToggleWarningOnGC",
                },
                forcegc = {
                        type = 'execute',
                        name = L"Force garbage collection",
                        desc = L"Force a garbage collection to happen",
                        order = 101,
                        func = collectgarbage
                }
        }
}
PerformanceFu:RegisterChatCommand(L:GetTable("AceConsole-options"), options)
PerformanceFu.OnMenuRequest = options

local gccheck = setmetatable({[{}]=true}, {__mode = "k"})

function PerformanceFu:OnUpdate()
        if justEntered then
                if not timeSinceLastUpdate then
                        timeSinceLastUpdate = 0
                end
                timeSinceLastUpdate = timeSinceLastUpdate + 1
                if timeSinceLastUpdate >= 10 then
                        initialMemory, gcThreshold = gcinfo()
                        currentMemory = initialMemory
                        mem1 = currentMemory
                        mem2 = currentMemory
                        mem3 = currentMemory
                        mem4 = currentMemory
                        mem5 = currentMemory
                        mem6 = currentMemory
                        mem7 = currentMemory
                        mem8 = currentMemory
                        mem9 = currentMemory
                        mem10 = currentMemory
                        timeSinceLastUpdate = nil
                        gcTime = time()
                        justEntered = false
                end
        else
                local t = time()
                timeSinceLastUpdate = 0
                mem1, mem2, mem3, mem4, mem5, mem6, mem7, mem8, mem9, mem10 =
                        currentMemory, mem1, mem2, mem3, mem4, mem5, mem6, mem7, mem8, mem9
                currentMemory, gcThreshold = gcinfo()
                if not next(gccheck) then
                        gccheck[{}] = true
                        initialMemory = currentMemory
                        gcTime = t
                        mem10, mem9, mem9, mem8, mem7, mem6, mem5, mem4, mem3, mem2, mem1 =
                                currentMemory, currentMemory, currentMemory, currentMemory, currentMemory, currentMemory, currentMemory, currentMemory, currentMemory, currentMemory
                        beeps5 = 0
                        beeps5 = 0
                        beeps15 = 0
                        beeps30 = 0
                        beeps60 = 0
                        beeps180 = 0
                        beeps600 = 0
                        if self:IsWarningOnGC() then
                                self:Print(L"Garbage collection occurred")
                        end
                end
                local averageRate = (currentMemory - initialMemory) / (t - gcTime)
                local totalSecs = (gcThreshold - currentMemory) / averageRate
                if self:IsWarningOnGC() then
                        if totalSecs <= 5 and beeps5 < t - 15 then
                                self:Print(L"Garbage collection in %s", Abacus:FormatDurationShort(totalSecs, false, true))
                                beeps600 = t
                                beeps180 = t
                                beeps60 = t
                                beeps30 = t
                                beeps15 = t
                                beeps5 = t
                        elseif totalSecs <= 15 and beeps15 < t - 30 then
                                self:Print(L"Garbage collection in %s", Abacus:FormatDurationShort(totalSecs, false, true))
                                beeps600 = t
                                beeps180 = t
                                beeps60 = t
                                beeps30 = t
                                beeps15 = t
                        elseif totalSecs <= 30 and beeps30 < t - 45 then
                                self:Print(L"Garbage collection in %s", Abacus:FormatDurationShort(totalSecs, false, true))
                                beeps600 = t
                                beeps180 = t
                                beeps60 = t
                                beeps30 = t
                        elseif totalSecs <= 60 and beeps60 < t - 90 then
                                self:Print(L"Garbage collection in %s", Abacus:FormatDurationShort(totalSecs, false, true))
                                beeps600 = t
                                beeps180 = t
                                beeps60 = t
                        elseif totalSecs <= 180 and beeps180 < t - 270 then
                                self:Print(L"Garbage collection in %s", Abacus:FormatDurationShort(totalSecs, false, true))
                                beeps600 = t
                                beeps180 = t
                        elseif totalSecs <= 600 and beeps600 < t - 900 then
                                self:Print(L"Garbage collection in %s", Abacus:FormatDurationShort(totalSecs, false, true))
                                beeps600 = t
                        end
                end
                self:Update()
        end
end

local t = {}
function PerformanceFu:OnTextUpdate()
        if not mem10 then
                mem10 = currentMemory
        end
        local currentRate = (currentMemory - mem10) / 10
        
        if self:IsShowingFramerate() then
                local framerate = floor(GetFramerate() + 0.5)
                table_insert(t, format("|cff%s%d|r fps", Crayon:GetThresholdHexColor(framerate / 60), framerate))
        end
        if self:IsShowingLatency() then
                local _,_,latency = GetNetStats()
                table_insert(t, format("|cff%s%d|r ms", Crayon:GetThresholdHexColor(latency, 1000, 500, 250, 100, 0), latency))
        end
        if self:IsShowingMemory() then
                table_insert(t, format("|cff%s%.1f|r MiB", Crayon:GetThresholdHexColor(currentMemory, 51200, 40960, 30520, 20480, 10240), currentMemory / 1024))
        end
        if self:IsShowingRate() then
                table_insert(t, format("|cff%s%.1f|r KiB/s", Crayon:GetThresholdHexColor(currentRate, 30, 10, 3, 1, 0), currentRate))
        end
        self:SetText(table_concat(t, " "))
        for k in pairs(t) do
                t[k] = nil
                k = nil
        end
        table_setn(t, 0)
end

function PerformanceFu:OnTooltipUpdate()
        local cat = Tablet:AddCategory(
                'columns', 2,
                'child_textR', 1,
                'child_textG', 1,
                'child_textB', 0
        )
        local framerate = GetFramerate()
        local r, g, b = Crayon:GetThresholdColor(framerate / 60)
        cat:AddLine(
                'text', L"Framerate:",
                'text2', string_format("%.1f fps", framerate),
                'text2R', r,
                'text2G', g,
                'text2B', b
        )
        
        cat = Tablet:AddCategory(
                'text', L"Network status",
                'columns', 2,
                'child_textR', 1,
                'child_textG', 1,
                'child_textB', 0,
                'child_text2R', 1,
                'child_text2G', 1,
                'child_text2B', 1
        )
        local bandwidthIn, bandwidthOut, latency = GetNetStats()
        bandwidthIn, bandwidthOut = bandwidthIn * 1024, bandwidthOut * 1024
        local r, g, b = Crayon:GetThresholdColor(latency, 3000, 1000, 250, 100, 0)
        cat:AddLine(
                'text', L"Latency:",
                'text2', string_format("%d ms", latency),
                'text2R', r,
                'text2G', g,
                'text2B', b
        )
        
        cat:AddLine(
                'text', L"Bandwidth in:",
                'text2', string_format("%d B/s", bandwidthIn)
        )
        
        cat:AddLine(
                'text', L"Bandwidth out:",
                'text2', string_format("%d B/s", bandwidthOut)
        )
        
        local averageRate = (currentMemory - initialMemory) / (time() - gcTime)
        cat = Tablet:AddCategory(
                'text', L"Memory usage",
                'columns', 2,
                'child_textR', 1,
                'child_textG', 1,
                'child_textB', 0,
                'child_text2R', 1,
                'child_text2G', 1,
                'child_text2B', 1
        )
        local currentRate = (currentMemory - mem10) / 10
        
        local r, g, b = Crayon:GetThresholdColor(currentMemory, 51200, 40960, 30520, 20480, 10240)
        cat:AddLine(
                'text', L"Current memory:",
                'text2', string_format("%.1f MiB", currentMemory / 1024),
                'text2R', r,
                'text2G', g,
                'text2B', b
        )
        
        r, g, b = Crayon:GetThresholdColor(initialMemory, 51200, 40960, 30520, 20480, 10240)
        cat:AddLine(
                'text', L"Initial memory:",
                'text2', string_format("%.1f MiB", initialMemory / 1024),
                'text2R', r,
                'text2G', g,
                'text2B', b
        )
        
        r, g, b = Crayon:GetThresholdColor(currentRate, 30, 10, 3, 1, 0)
        cat:AddLine(
                'text', L"Increasing rate:",
                'text2', string_format("%.1f KiB/s", currentRate),
                'text2R', r,
                'text2G', g,
                'text2B', b
        )
        
        r, g, b = Crayon:GetThresholdColor(averageRate, 30, 10, 3, 1, 0)
        cat:AddLine(
                'text', L"Average increasing rate:",
                'text2', format("%.1f KiB/s", averageRate),
                'text2R', r,
                'text2G', g,
                'text2B', b
        )
        
        cat = Tablet:AddCategory(
                'text', L"Garbage collection",
                'columns', 2,
                'child_textR', 1,
                'child_textG', 1,
                'child_textB', 0,
                'child_text2R', 1,
                'child_text2G', 1,
                'child_text2B', 1
        )
        
        local totalSecs = (gcThreshold - currentMemory) / averageRate
        local timeToNext = Abacus:FormatDurationFull(totalSecs)
        
        local r, g, b = Crayon:GetThresholdColor(gcThreshold, 51200, 40960, 30520, 20480, 10240)
        cat:AddLine(
                'text', L"Threshold:",
                'text2', format("%.1f MiB", gcThreshold / 1024),
                'text2R', r,
                'text2G', g,
                'text2B', b
        )
        
        local r, g, b = Crayon:GetThresholdColor(totalSecs, 0, 900, 1800, 2700, 3600)
        cat:AddLine(
                'text', L"Time to next:",
                'text2', timeToNext,
                'text2R', r,
                'text2G', g,
                'text2B', b
        )
end