Thread Tools Display Modes
04-26-10, 05:29 AM   #1
Goatus
A Deviate Faerie Dragon
AddOn Author - Click to view addons
Join Date: Jan 2005
Posts: 18
Something weird

So im coding chat addon, and while doing some testing i noticed it builds huge up amounts of memory if i mouseover chat window a lot (easily can top memory usage).

After some investigation I found the cause but I don't really know why it behaves this way. So the code responsible for huge mem usage looks like this:


Code:
local dummy = function() end

Code:
local function initChatFrame(chatFrame, i)
        local chatElement
	
        ...
	
        --hides chat bg
	chatElement = chatFrame:GetRegions()
	chatElement.Show = dummy
	chatElement:Hide()

        ...
end
Changing first code snippet to
Code:
local dummy = nil
solves the problem, but i still want to know why this happens. Anyone Lua savvy can explain please?
  Reply With Quote
04-26-10, 06:25 AM   #2
Beoko
Guest
Posts: n/a
It depends where and how often that function is being called. Could you please post the rest of your code?
  Reply With Quote
04-26-10, 07:50 AM   #3
Goatus
A Deviate Faerie Dragon
AddOn Author - Click to view addons
Join Date: Jan 2005
Posts: 18
Well
Code:
 initChatFrame(chatFrame, i)
is called only once for every active ChatFrame on PLAYER_LOGIN if thats what you asking.

As for
Code:
 chatElement.Show = dummy
its just short for
Code:
_G[chatFrame .. i .. "Background"].Show = dummy
and i have no idea how often ChatFrameNBackground:Show() is called, but i believe it's at least once for every mousover.

Still from what i understand calling empty function shouldn't generate any garbage should it?
  Reply With Quote
04-26-10, 03:21 PM   #4
Goatus
A Deviate Faerie Dragon
AddOn Author - Click to view addons
Join Date: Jan 2005
Posts: 18
Well I'm blind and my problem isn't solved as i thought before

Code:
chatElement.Show = nil
actually does nothing (ie doesn't prevent chat parts from showing) so im left with
Code:
 chatElement.Show = function() end
which generates tons of garbage on frequent mouse over, any idea why?

Here is full code for that lua file (even tho i don't believe it's relevant )

lua Code:
  1. --Get namespace
  2. local addonName, addon = ...
  3.  
  4. --localize config
  5. local cfg = addon.cfg
  6.  
  7. --Keep references to new and some default frames
  8. addon.chatFrames = {}
  9. addon.chatTabs = {}
  10. addon.nChatArt = {}
  11. addon.nTabArt = {}
  12. addon.nChatButtons = {}
  13. addon.tabControl = {}
  14.  
  15. --some localized functions
  16. local unpack, select = unpack, select
  17.  
  18. --Helper
  19. local dumy = nil
  20.  
  21. --Hide chat elements (buttons, background and border), create frame with custom background and border
  22. local function initChatFrame(chatFrame, id)
  23.     local chatElement
  24.     local newFrame
  25.    
  26.     --Disable  drawing of background layer for all border elements (can't hide those cause they allow to resize chat frame)
  27.     for i = 1, 8 do
  28.         chatElement = select(i, chatFrame:GetChildren())
  29.         chatElement:DisableDrawLayer('BACKGROUND')
  30.     end
  31.    
  32.     --Hide chat buttons, and make sure they stay that way
  33.     for i = 9, 11 do
  34.         chatElement = select(i, chatFrame:GetChildren())
  35.         chatElement.Show = function() end
  36.         chatElement:Hide()
  37.     end
  38.    
  39.     --Now disable chat background which should be first region of ChatFrame
  40.     chatElement = chatFrame:GetRegions()
  41.     chatElement.Show = function() end
  42.     chatElement:Hide()
  43.    
  44.     --Create frame that will serve as a custom background and border
  45.     newFrame = CreateFrame('Frame', nil, chatFrame)
  46.     --Need to make it bit bigger so it looks ok
  47.     newFrame:SetPoint('TOPLEFT', chatFrame, 'TOPLEFT', -2, 2)
  48.     newFrame:SetPoint('BOTTOMRIGHT', chatFrame, 'BOTTOMRIGHT', 2, -2)
  49.     --Add custom backdrop
  50.     newFrame:SetBackdrop(addon.cfg.backdropStyle)
  51.     newFrame:SetBackdropColor(unpack(addon.cfg.chatBGColor))
  52.     newFrame:SetBackdropBorderColor(unpack(addon.cfg.chatBorderColor))
  53.    
  54.     --Move it under chatFrame
  55.     newFrame:SetFrameLevel(chatFrame:GetFrameLevel() - 1)  
  56.    
  57.     --Clamp to screen
  58.     chatFrame:SetClampedToScreen(true)
  59.  
  60.     --Change parent to control frame to make combat fading easy
  61.     chatFrame:SetParent(addon.control)
  62.    
  63.     --Add chat frame and new bg frame to tables for easy acces
  64.     addon.chatFrames[id] = chatFrame
  65.     addon.nChatArt[id] = newFrame
  66. end
  67.  
  68. --Do some morel stuff with chat
  69. local function chatPostInit()
  70.     --Hide emote menu
  71.     ChatFrameMenuButton.Show = dumy
  72.     ChatFrameMenuButton:Hide()
  73. end
  74.  
  75. --Do full initialization on all chat window elements (chat frame / tabs etc)
  76. addon.initChatWindow = function(id)
  77.     local chatFrame = _G['ChatFrame'..id]
  78.    
  79.     --Initialize chat frame
  80.     initChatFrame(chatFrame, id)
  81.        
  82.     --Initialize chat tab
  83.     addon.initTabFrame(chatFrame, id)
  84.        
  85.     --Add timestamps
  86.     addon.addTimestamp(chatFrame)
  87.        
  88.     --Add mousescrolling
  89.     addon.initScroll(chatFrame, id)
  90. end
  91.  
  92. --Prepare frames
  93. local function init()
  94.  
  95.     --Proces all chat frames and their elements
  96.     for i = 1, FCF_GetNumActiveChatFrames() do
  97.         addon.initChatWindow(i)
  98.     end
  99.    
  100.     --Do some more stuff
  101.     chatPostInit()
  102.     addon.tabPostInit()
  103.     addon.initEditbox()
  104.     addon.autohideInit()
  105. end
  106.  
  107. --Initialize everything on PLAYER_LOGIN some information isnt aviable earlier
  108. local function onLoad(self, event, arg1)
  109.     init() 
  110.     self:UnregisterAllEvents()
  111. end
  112.  
  113. --main frame
  114. local frame = CreateFrame('Frame', nil, UIParent)
  115. frame:RegisterEvent('PLAYER_LOGIN')
  116. frame:SetScript('OnEvent', onLoad)
  117.  
  118. --Frame for combat fading control
  119. addon.control = CreateFrame('Frame', nil, UIParent)

BTW What are tags for luacode? I saw in few post proper syntax coloring of lua but can't find how to do it

Last edited by Goatus : 04-26-10 at 04:30 PM.
  Reply With Quote
04-26-10, 03:40 PM   #5
Sekrin
A Chromatic Dragonspawn
AddOn Author - Click to view addons
Join Date: Jul 2008
Posts: 150
Calling empty functions does use memory, about 20 bytes per call according to http://www.wowwiki.com/Lua_object_memory_sizes
__________________
  Reply With Quote
04-26-10, 04:14 PM   #6
ravagernl
Proceritate Corporis
Premium Member
AddOn Author - Click to view addons
Join Date: Feb 2006
Posts: 1,176
Originally Posted by Goatus View Post
BTW What are tags for luacode? I saw in few post proper syntax coloring of lua but can't find how to do it
[ highlight=lua ]
lua Code:
  1. local a, b, c = 1, 2, 3
  2. if a == 1 or b == 2 or c == 3 then
  3.     DoStuff()
  4. end
  Reply With Quote
04-26-10, 04:24 PM   #7
Goatus
A Deviate Faerie Dragon
AddOn Author - Click to view addons
Join Date: Jan 2005
Posts: 18
Originally Posted by Sekrin View Post
Calling empty functions does use memory, about 20 bytes per call according to http://www.wowwiki.com/Lua_object_memory_sizes
Yes and no.
What i mean: I know that it theoretically uses memory but lua should menage it so it doesn't grow that rapidly. In same code i do
lua Code:
  1. chatTab:HookScript('OnEnter', function(self) newFrame.hover = true updateTabColors(newFrame) end)

Which fires every time i mouse over chat tab, and is definetly more complex that function() end right? But my addon memory doesn't even twitch while I'm hovering those tabs in/out like madman

But in just 15s with this flawed code from first post i can go well over 1 MiB in resource tools memory usage. So there is definitely something terribly wrong.

Edit:Thanks mrruben5!

Last edited by Goatus : 04-26-10 at 04:28 PM.
  Reply With Quote
04-27-10, 03:32 AM   #8
Beoko
Guest
Posts: n/a
A simple alternative would be:
Code:
DEFAULT_CHATFRAME_ALPHA = 0
I was able to recreate your circumstances with this:

Code:
local Fake = function() end
local AddOn = CreateFrame("Frame")
AddOn:RegisterEvent("PLAYER_LOGIN")
AddOn:SetScript("OnEvent", function()
    for Index = 1, 7 do
        local BG = _G["ChatFrame" .. Index .. "Background"]
        BG.Show = Fake
        BG:Hide()
    end
end)
My conclusion is that rewriting the state of ChatFrame backgrounds simply incurs a high cost. I don't think it needs to be looked into deeply since there are cheaper (and easier) alternatives that accomplish the same goal.
  Reply With Quote
04-27-10, 07:07 AM   #9
Slakah
A Molten Giant
 
Slakah's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2007
Posts: 863
Originally Posted by Sekrin View Post
Calling empty functions does use memory, about 20 bytes per call according to http://www.wowwiki.com/Lua_object_memory_sizes
Creating empty functions uses memory whereas calling them should use none.
  Reply With Quote
04-27-10, 07:28 AM   #10
Goatus
A Deviate Faerie Dragon
AddOn Author - Click to view addons
Join Date: Jan 2005
Posts: 18
Well I'm currently just disabling background layer (:DisableDrawLayer()) and it works.

Still i wonder if maybe this is something worth reporting to Blizzard, cause it looks like some kind of memory leak somewhere in their code to me.

Anyways thanks for all the help and suggestions :)

Last edited by Goatus : 04-27-10 at 08:15 AM.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Something weird

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off