魔兽世界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
相关产品推荐
相关产品推荐

