You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

魔兽世界Lua插件GraphDPS内存泄漏问题求助

魔兽世界插件内存持续增长问题

这是我开发的第一款魔兽世界插件,也是我的第一个Lua程序。插件用于捕获战斗日志事件,在名为db1的表中存储每秒伤害数据,该表最多保留50条记录。初始时插件仅占用39KB内存,但运行后内存持续增长(通过GetAddOnMemoryUsage("GraphDPS")观测)。即使在内存达到初始值两倍时调用collectgarbage("collect"),最终仍会导致游戏卡顿。

以下是插件代码:

-- ================================= VARIABLES ================================== --
-- Globals, only used when login and log out
GDPS_damae = 0
GDPS_db1 = {}
GDPS_db3 = {}
GDPS_frgfh = 238
GDPS_frgfw = 83
GDPS_unvu = {}
-- Locals
local coei = nil                         -- combat : CombatLog Event Infos
local colib = "Dernier combat"           -- combat : "Dernier combat" ou combat actuel"
local cosc = 0                           -- combat : compteur de seconde du combat en cours
local damae = 0                          -- data : biggest dps ever
local datalc = 0                         -- data :total amount last combat
local db1 = {}                           -- database 1
local db1l = 50                          -- database 1 limit
local db1le = {nil, nil}                 -- database : database 1 last entry
local db1nv = 0                          -- database : database 1 number of values
local db1nvn = 0                         -- database : database 1 number of values numerical
local db3 = {}                           -- database : database 3
local evt = ""                           -- event : type
local eva = 0                            -- event : amount
local evsn = ""                          -- event : swing or spell
local fra = 0                            -- frames alpha
local tic = 0                            -- timer : every second in combat
local tmce = 0                           -- timestamp : combat end (PLAYER_REGEN_ENABLED)
local tmcel = 0                          -- timestamp : combat end
local tmdce = 0                          -- timestamp : combat end delta
local tmia = 0                           -- timestamp : timstamp in analyse
local tmiaa = 0                          -- timestamp : timestamp in analyse amount
local tmlcs = 0                          -- timestamp : timestamp last combat start
local tmoe = 0                           -- timestamp : timestamp of event
local tmprd = 0                          -- timestamp : timestamp combat start (PLAYER_REGEN_DISABLED)
local unUID = UnitGUID("player")         -- units : player
local unUIDe = ""                        -- units : of event
local unvu = {}                          -- units : list of valid units
unvu[unUID] = true
-- ============================= LOCALISED FUNCTIONS ============================ --
local C_Timer = C_Timer
local CombatLogGetCurrentEventInfo = CombatLogGetCurrentEventInfo
local CreateFrame = CreateFrame
local mathfloor = math.floor
local tableremove = table.remove 
local type = type
-- ================================= FONCTIONS ================================== --
-- obtenir timestamps courant sans virgule
---@return number
local function tmr()
    return mathfloor(time())
end
-- mise à jour du plus gros dps enregistré
local function daum()
    if tmiaa > damae then
        damae = tmiaa
    end     
end
-- efface la plus ancienne donnée dans db1
local function db1doe()
    db1nv = db1nv - 1
    if type(db1[1][2]) == "number" then
        db1nvn    = db1nvn - 1
    end 
    tableremove(db1, 1)
end
-- ajoute une entrée dans db1
---@param t number
---@param v number or string
local function db1ad(t, v)
    if #db1 == db1l then
        db1doe()
    end
    db1[#db1+1] = {t, v} --
    db1nv = db1nv + 1
    if type(v) == "number" then
        db1nvn = db1nvn + 1
        daum()
    end
    db1le = {t, v} --
end
-- =================== FRAMES ET FONCTIONS PROPRES AUX FRAMES =================== --
local frm1 = CreateFrame("Frame", "GraphDPS main graph frame", UIParent)
frm1:SetSize(260, 80)
frm1:SetPoint("CENTER", UIParent, "CENTER", 0, 0 )
frm1.tex = frm1:CreateTexture()
frm1.tex:SetAllPoints(frm1)
frm1.tex:SetColorTexture(0,0,0,fra)
frm1:EnableDrawLayer("ARTWORK")

-- =================================== EVENTS =================================== --
frm1:RegisterEvent("ADDON_LOADED")
frm1:RegisterEvent("PLAYER_LOGOUT")
frm1:RegisterEvent("PLAYER_REGEN_DISABLED")
frm1:RegisterEvent("PLAYER_REGEN_ENABLED")
frm1:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
local function eventH(self, event, ...)
    if event == "PLAYER_LOGOUT" then 
        GDPS_frgfh = frm1:GetWidth()
        GDPS_frgfw = frm1:GetHeight()
        GDPS_db1 = db1
        GDPS_db3 = db3
        GDPS_damae = damae
        GDPS_unvu = unvu
    end
    if event == "ADDON_LOADED" then
        db1 = GDPS_db1
        db3 = GDPS_db3
        demae = GDPS_damae
    end
    if event == "PLAYER_REGEN_DISABLED" then
        tmprd = tmr()
        colib = "Combat actuel"
        tic = 0
        tmdce = 1
        datalc = 0
        db1ad(tmprd, "cs")
        db3={}
        tic = C_Timer.NewTicker(1, function()
            if tmia - db1le[1] > 1 then db1ad(db1le[1]+1, 0) end
            if tmia < tmlcs + cosc then db1ad(db1le[1]+1, 0) end 
            cosc = cosc + 1
            tmdce = tmdce + 1
        end)
    end
    if event == "PLAYER_REGEN_ENABLED" then
        tic:Cancel()
        colib = "Dernier combat"
        cosc = 0
        tmcel = tmr()
        if db1le[1] ~= tmia or db1le[2] == "cs" then db1ad(tmia, tmiaa) end
        tmdce = 0
        for i = db1le[1] + 1, tmce - 1 do
            db1ad(i, 0)
            tmdce = tmdce + 1
        end
        db1ad(tmcel, "ce")
        tmia = 0
        tmiaa = 0
        tmce = tmcel
    end
    if event == "COMBAT_LOG_EVENT_UNFILTERED" then
        if colib == "Combat actuel" then
            tmoe, evt, _, unUIDe = select(1, CombatLogGetCurrentEventInfo())
            tmoe = mathfloor(tmoe)
            -- l'ajout des pet reste à voir
            if unvu[unUIDe] ~= nil then
                if evt == "SWING_DAMAGE" then
                    eva = select(12, CombatLogGetCurrentEventInfo())
                    evsn = "swing"
                elseif evt == "SPELL_DAMAGE" or evt == "SPELL_PERIODIC_DAMAGE" or evt == "RANGE_DAMAGE" then
                    evsn, _, eva = select(13, CombatLogGetCurrentEventInfo())
                end
                if evt == "SWING_DAMAGE" or evt == "SPELL_DAMAGE" or evt == "SPELL_PERIODIC_DAMAGE" or evt == "RANGE_DAMAGE" then
                    if type(eva) == "number" then
                        if eva > damae then
                            damae = eva
                        end
                        if db3[evsn] ~= nil then
                            db3[evsn] = db3[evsn] + eva
                        else
                            db3[evsn] = eva
                        end            
                        if tmia ~= 0 then
                            if tmia == tmoe then
                                tmiaa = tmiaa + eva
                            else
                                db1ad(tmia, tmiaa)
                                tmia = tmoe
                                tmiaa = eva
                            end
                        else
                            tmia = tmoe
                            tmiaa = eva
                        end
                    end
                    datalc = datalc + eva
                end
            --else
                -- l'ajout des dégâts des invoqués viendra après
            end
        end
    end
end
frm1:SetScript("OnEvent", eventH)

内容的提问来源于stack exchange,提问作者Fafa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 02:07:01