Thread Tools Display Modes
07-10-19, 08:03 AM   #1
Terenna
A Flamescale Wyrmkin
AddOn Author - Click to view addons
Join Date: Jun 2016
Posts: 105
Minimap Coordinates Memory Usage Optimization

The following code is used within my personal minimap addon. The code will cause a constant 3 kb/second gain of memory until garbage collection is run, and goes back down quite low. Is there a way to run this and not have constant garbage being built?

Lua Code:
  1. local x, y, mapPosObject, mapID
  2. tMinimapCoordsFrame:SetScript('OnUpdate', function(self, elapsed)
  3.     self.elapsed = self.elapsed + elapsed
  4.     while self.elapsed > 0.5 do --only update the coords 2/second
  5.         mapID = C_Map.GetBestMapForUnit('player')
  6.         if mapID then
  7.             mapPosObject = C_Map.GetPlayerMapPosition(mapID, 'player')
  8.             if mapPosObject then
  9.                 x, y = mapPosObject:GetXY()
  10.             end
  11.             if (x and (x + y > 0)) then --hide if we don't have coords (instances)
  12.                 tMinimapCoordsFrame.text:SetFormattedText('%.1f, %.1f', x*100, y*100)
  13.             else
  14.                 tMinimapCoordsFrame:Hide()
  15.             end
  16.         end
  17.  
  18.         self.elapsed = self.elapsed - 0.5
  19.     end
  20. end)
  Reply With Quote
07-10-19, 08:48 AM   #2
kurapica.igas
A Chromatic Dragonspawn
Join Date: Aug 2011
Posts: 152
Because the C_Map.GetPlayerMapPosition always create a new table as the result, so the memory usage will constantly increasing.

Here is a solution from other author:

Lua Code:
  1. local MapRects                  = {}
  2. function GetPlayerMapPos()
  3.     local mapid                 = C_Map.GetBestMapForUnit('player')
  4.     if not mapid then return end
  5.  
  6.     local rects                 = MapRects[mapid]
  7.  
  8.     if not rects then
  9.         rects                   = {}
  10.         local _, topleft        = C_Map.GetWorldPosFromMapPos(mapid, CreateVector2D(0,0))
  11.         local _, bottomright    = C_Map.GetWorldPosFromMapPos(mapid, CreateVector2D(1,1))
  12.  
  13.         bottomright:Subtract(topleft)
  14.         rects                   = { topleft.x, topleft.y, bottomright.x, bottomright.y }
  15.         MapRects[mapid]         = rects
  16.     end
  17.  
  18.     local x, y                  = UnitPosition("player")
  19.     if not x then return end
  20.  
  21.     x, y                        = x - rects[1], y - rects[2]
  22.  
  23.     return y / rects[4], x / rects[3]
  24. end
  Reply With Quote
07-10-19, 09:13 AM   #3
Terenna
A Flamescale Wyrmkin
AddOn Author - Click to view addons
Join Date: Jun 2016
Posts: 105
Absolutely brilliant, thank you so much!
  Reply With Quote
07-10-19, 10:41 AM   #4
jeruku
A Cobalt Mageweaver
 
jeruku's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2010
Posts: 223
May have gone a little overboard but this should increase performance significantly.

Edit: Decided to take out the comments after fixing it up; I'm clearly bad at explaining myself.
Lua Code:
  1. local GetBestMapForUnit = C_Map.GetBestMapForUnit  
  2. local MapRects =  {}
  3. local mapID
  4. local UnitPosition =  UnitPosition
  5. local GetWorldPosFromMapPos =  C_Map.GetWorldPosFromMapPos
  6. local CreateVector2D =  CreateVector2D
  7.  
  8. local function GetPlayerMapPosition(mapid, token, rects, _, x, y)
  9.     if mapid then
  10.         rects = MapRects[mapid]
  11.         if not rects then
  12.             rects = {}
  13.             _, topleft = GetWorldPosFromMapPos(mapid, CreateVector2D(0,0))
  14.             _, bottomright = GetWorldPosFromMapPos(mapid, CreateVector2D(1,1))
  15.  
  16.             bottomright:Subtract(topleft)
  17.             rects = { topleft.x, topleft.y, bottomright.x, bottomright.y }
  18.             MapRects[mapid] = rects
  19.         end
  20.  
  21.         x, y = UnitPosition(token)
  22.         if x then
  23.             x, y = x - rects[1], y - rects[2]
  24.             return y / rects[4], x / rects[3]
  25.         else
  26.             return 0, 0
  27.         end
  28.     end
  29. end
  30.  
  31. local function OnUpdate(self, elapsed, x, y)
  32.     if mapID then
  33.         x, y = GetPlayerMapPosition(mapID, 'player')
  34.         self.text:SetFormattedText('%.1f, %.1f', x*100, y*100)
  35.     end
  36. end
  37. tMinimapCoordsFrame:HookScript('OnUpdate', OnUpdate)
  38.  
  39. tMinimapCoordsFrame:HookScript('OnEvent', function(self, event, ...)
  40.     if event == 'PLAYER_STOPPED_MOVING' then
  41.         mapID = nil
  42.     elseif event ~= 'PLAYER_ENTERING_WORLD' then
  43.         mapID = GetBestMapForUnit('player')
  44.     else
  45.         mapID = GetBestMapForUnit('player')
  46.         OnUpdate(self)
  47.         self:UnregisterEvent('PLAYER_ENTERING_WORLD')
  48.     end
  49. end)
  50. tMinimapCoordsFrame:RegisterEvent('ZONE_CHANGED')
  51. tMinimapCoordsFrame:RegisterEvent('ZONE_CHANGED_INDOORS')
  52. tMinimapCoordsFrame:RegisterEvent('ZONE_CHANGED_NEW_AREA')
  53. tMinimapCoordsFrame:RegisterEvent('PLAYER_ENTERING_WORLD')
  54. tMinimapCoordsFrame:RegisterEvent('PLAYER_STOPPED_MOVING')
  55. tMinimapCoordsFrame:RegisterEvent('PLAYER_STARTED_MOVING')
__________________
"I have not failed, I simply found 10,000 ways that did not work." - Thomas Edison

Last edited by jeruku : 07-10-19 at 08:59 PM. Reason: Okay, totally fixed... hopefully.
  Reply With Quote
07-10-19, 02:06 PM   #5
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,313
Originally Posted by jeruku View Post
Lua Code:
  1. -- Move global functions into the frames table; you could also make them locals, like below, but I prefer this method.
  2. --     local GetWorldPosFromMapPos = C_Map.GetWorldPosFromMapPos
  3. tMinimapCoordsFrame.MapRects =  {}
  4. tMinimapCoordsFrame.UnitPosition =  UnitPosition
  5. tMinimapCoordsFrame.GetWorldPosFromMapPos =  C_Map.GetWorldPosFromMapPos
  6. tMinimapCoordsFrame.CreateVector2D =  CreateVector2D
Moving local references to globals into a table defeats the purpose of making them in the first place, which is to save on indexing operations. You run the same number of these operations pulling them from your table as you would calling them as globals.



Originally Posted by jeruku View Post
Lua Code:
  1. --    I dislike strings in OnUpdate; again, personal preference.
  2.  
  3. tMinimapCoordsFrame.FromattedString = '%.1f, %.1f'
  4. tMinimapCoordsFrame.PlayerToken = 'player'
These actually create indexing operations in the following OnUpdate script as opposed to them being stored as a part of the function binary as a constant. All literal values are constants referred to when used in an expression. In the long run, this actually slows down the function instead of offering any performance boost.



Originally Posted by jeruku View Post
Lua Code:
  1. local function Blank_OnUpdate() end
  2. local OnUpdate = Blank_OnUpdate
  3.  
  4. tMinimapCoordsFrame:HookScript('OnUpdate', OnUpdate)
  5.  
  6. --  Getting the mapID every OnUpdate is rather inefficient, get it when it changes/loads
  7. local GetBestMapForUnit = C_Map.GetBestMapForUnit
  8. tMinimapCoordsFrame:HookScript('OnEvent', function(self, event, ...)
  9.     if event == 'PLAYER_STARTED_MOVING' then --  Self explanatory event
  10.         OnUpdate = Do_OnUpdate
  11.     elseif event == 'PLAYER_STOPPED_MOVING' then
  12.         OnUpdate = Blank_OnUpdate
  13.     elseif event == 'ZONE_CHANGED' or event == 'ZONE_CHANGED_INDOORS' or event == 'ZONE_CHANGED_NEW_AREA' or event == 'PLAYER_ENTERING_WORLD'  then
  14.         self.mapID = GetBestMapForUnit('player')
  15.                 Do_OnUpdate(self, self.mapID)
  16.     end
  17. end)
This way of swapping OnUpdate scripts doesn't work at all. It doesn't magically tell the function to watch OnUpdate for changes, it just ends up grabbing Blank_OnUpdate() on initialization and further changes in the event script does nothing. Since the OP used :SetScript() to assign the function in the first place, it's safe to assume you can run :SetScript("OnUpdate",nil) to clear and set it again when necessary. Otherwise, you can set an upvalue to flag and have the script check it when it's to run.
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)

Last edited by SDPhantom : 07-10-19 at 02:32 PM.
  Reply With Quote
07-10-19, 02:36 PM   #6
Terenna
A Flamescale Wyrmkin
AddOn Author - Click to view addons
Join Date: Jun 2016
Posts: 105
I've been coding my UI casually for ~ 6 years. Turns out I'm still garbage at it compared to you all. It's incredible how absolutely complex you can get to squeeze every inch out of CPU/RAM if you sit down and really go for it.
  Reply With Quote
07-10-19, 03:10 PM   #7
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 2,313
It's the nature of being in a community. You can pick up things from others you might have never come across on your own.
__________________
WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)
  Reply With Quote
07-10-19, 08:56 PM   #8
jeruku
A Cobalt Mageweaver
 
jeruku's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2010
Posts: 223
Originally Posted by SDPhantom View Post
Moving local references to globals into a table defeats the purpose of making them in the first place, which is to save on indexing operations. You run the same number of these operations pulling them from your table as you would calling them as globals.
Think there was a misunderstanding, it's not an upvalue but rather the global itself. If you wanna get super technical it would be the same as sometable.UnitPosition = _G["UnitPosition"].

And to my knowledge a table lookup inside a function from a passed variable(self or vararg) is faster than calling a variable from outside of scope. In the cases where you're dealing with a single frame it takes up the same amount of space and is only slightly faster; if you were using OnUpdate on something like hundreds/thousands of frames it would be a trade off between CPU vs RAM depending on the number/type of things added to, or used from, the table. Sadly I'm used to doing it this way and it's certainly a bad habit.

Originally Posted by SDPhantom View Post
All literal values are constants referred to when used in an expression.
I don't always remember things correctly and again shoving everything into the table is a bad habit.

Originally Posted by SDPhantom View Post
This way of swapping OnUpdate scripts doesn't work at all.
Thanks for pointing that out, that was my bad and I have no excuse. I have absolutely no idea why I thought that would work. I corrected my post and will correct it further.
__________________
"I have not failed, I simply found 10,000 ways that did not work." - Thomas Edison
  Reply With Quote
07-11-19, 08:59 AM   #9
Terenna
A Flamescale Wyrmkin
AddOn Author - Click to view addons
Join Date: Jun 2016
Posts: 105
I modified it ever so slightly to this:
Lua Code:
  1. local GetBestMapForUnit = C_Map.GetBestMapForUnit  
  2. local MapRects = {}
  3. local mapID
  4. local UnitPosition = UnitPosition
  5. local GetWorldPosFromMapPos = C_Map.GetWorldPosFromMapPos
  6. local CreateVector2D = CreateVector2D
  7.  
  8. local function GetPlayerMapPosition(mapid, token, rects, _, x, y)
  9.     x, y = UnitPosition(token)
  10.     if not x then return end
  11.     if mapid then
  12.         rects = MapRects[mapid]
  13.         if not rects then
  14.             rects = {}
  15.             _, topleft = GetWorldPosFromMapPos(mapid, CreateVector2D(0,0))
  16.             _, bottomright = GetWorldPosFromMapPos(mapid, CreateVector2D(1,1))
  17.  
  18.             bottomright:Subtract(topleft)
  19.             rects = { topleft.x, topleft.y, bottomright.x, bottomright.y }
  20.             MapRects[mapid] = rects
  21.         end
  22.        
  23.         x, y = x - rects[1], y - rects[2]
  24.         return y / rects[4], x / rects[3]
  25.     end
  26. end
  27.  
  28. local function OnUpdate(self, elapsed, x, y)
  29.     self.elapsed = self.elapsed + elapsed
  30.     while self.elapsed > 0.5 do --only update the coords 2/second
  31.         if mapID then
  32.             x, y = GetPlayerMapPosition(mapID, 'player')
  33.             if x then
  34.                 self.text:SetFormattedText('%.1f, %.1f', x * 100, y * 100)
  35.             else
  36.                 self.text:SetText('')
  37.             end
  38.         end
  39.  
  40.         self.elapsed = self.elapsed - 0.5
  41.     end
  42. end
  43.  
  44. tMinimapCoordsFrame:SetScript('OnEvent', function(self, event, ...)
  45.     if event == 'PLAYER_STOPPED_MOVING' then
  46.         mapID = nil
  47.         tMinimapCoordsFrame:SetScript('OnUpdate', nil)
  48.     elseif event == 'PLAYER_STARTED_MOVING' then
  49.         mapID = GetBestMapForUnit('player')
  50.         tMinimapCoordsFrame:SetScript('OnUpdate', OnUpdate)
  51.     elseif event == 'ZONE_CHANGED_NEW_AREA' then
  52.         if IsInInstance() then
  53.             self:UnregisterEvent('PLAYER_STARTED_MOVING')
  54.             self:UnregisterEvent('PLAYER_STOPPED_MOVING')
  55.             self:UnregisterEvent('ZONE_CHANGED')
  56.             self:UnregisterEvent('ZONE_CHANGED_INDOORS')
  57.         else
  58.             self:RegisterEvent('PLAYER_STOPPED_MOVING')
  59.             self:RegisterEvent('PLAYER_STARTED_MOVING')
  60.             self:RegisterEvent('ZONE_CHANGED')
  61.             self:RegisterEvent('ZONE_CHANGED_INDOORS')
  62.         end
  63.     else
  64.         mapID = GetBestMapForUnit('player')
  65.         OnUpdate(self, 1) --force it to update the coords exactly once as we log in
  66.         self:UnregisterEvent('PLAYER_ENTERING_WORLD')
  67.         if IsInInstance() then
  68.             self:UnregisterEvent('PLAYER_STARTED_MOVING')
  69.             self:UnregisterEvent('PLAYER_STOPPED_MOVING')
  70.             self:UnregisterEvent('ZONE_CHANGED')
  71.             self:UnregisterEvent('ZONE_CHANGED_INDOORS')
  72.         end
  73.     end
  74. end)

I reworked the OnEvent handler to unregister and register the movement and zone changes if the player is in an instance so it won't be running in there where there are no coordinates.

Last edited by Terenna : 07-11-19 at 09:13 AM.
  Reply With Quote
07-11-19, 11:46 AM   #10
Lybrial
A Flamescale Wyrmkin
AddOn Compiler - Click to view compilations
Join Date: Jan 2010
Posts: 120
I use AceTimer-3.0 for updating my coords frame:

Lua Code:
  1. local CORE, LIBS = LybrialUI:GetCore();
  2. local LOCALE = LIBS.LOCALE;
  3.  
  4. local Texts = LybrialMiniMap:NewModule("Texts", "AceTimer-3.0");
  5.  
  6. Texts.displayName = LOCALE["TEXTS"];
  7. Texts.desc = LOCALE["TEXTS_DESC"];
  8. Texts.zone = nil;
  9. Texts.coords = nil;
  10. Texts.date = nil;
  11. Texts.clock = nil;
  12.  
  13. local _G = _G;
  14. local C_Map = C_Map;
  15. local CreateFrame = CreateFrame;
  16. local CreateVector2D = CreateVector2D;
  17. local GetMinimapZoneText = GetMinimapZoneText;
  18. local Minimap = Minimap;
  19. local UnitPosition = UnitPosition;
  20. local strsub = strsub;
  21. local unpack = unpack;
  22.  
  23. function Texts:OnEnableCoords()
  24.     if (not self.coords) then
  25.         self.coords = CreateFrame("Frame", "LybrialUITextsCoords", Minimap);
  26.         self.coords.text = self.coords:CreateFontString(nil, "OVERLAY");
  27.         self.coords.MapRects = {};
  28.         self.coords:SetScript("OnEvent", function(self)
  29.             self.mapId = C_Map.GetBestMapForUnit("player");
  30.         end);
  31.         self.coords:RegisterEvent("PLAYER_ENTERING_WORLD");
  32.         self.coords:RegisterEvent("ZONE_CHANGED");
  33.         self.coords:RegisterEvent("ZONE_CHANGED_INDOORS");
  34.         self.coords:RegisterEvent("ZONE_CHANGED_NEW_AREA");
  35.         self:ScheduleRepeatingTimer(self.UpdatePlayerMapPosition, 1);
  36.     end
  37. end
  38.  
  39. function Texts:OnUpdateCoords()
  40.     local show = self.db.profile.texts.coords.show;
  41.     local anchor = self.db.profile.texts.coords.position.anchor;
  42.     local offsetX = self.db.profile.texts.coords.position.offset.x;
  43.     local offsetY = self.db.profile.texts.coords.position.offset.y;
  44.     local font = self.db.profile.texts.coords.font.font;
  45.     local fontSize = self.db.profile.texts.coords.font.size;
  46.     local fontOutline = self.db.profile.texts.coords.font.outline;
  47.     local fontColor = self.db.profile.texts.coords.font.color;
  48.  
  49.     self.coords:SetSize(120, 30);
  50.     self.coords:ClearAllPoints();
  51.     self.coords:SetPoint(anchor, Minimap, anchor, offsetX, offsetY);
  52.     self.coords.text:ClearAllPoints();
  53.     self.coords.text:SetPoint("CENTER");
  54.     self.coords.text:SetFont(LIBS.LSM:Fetch("font", font), fontSize, fontOutline);
  55.     self.coords.text:SetTextColor(unpack(fontColor));
  56.  
  57.     if (show) then
  58.         self.coords:Show();
  59.     else
  60.         self.coords:Hide();
  61.     end
  62. end
  63.  
  64. function Texts:UpdatePlayerMapPosition()
  65.     local coords = Texts.coords;
  66.  
  67.     if (not coords:IsShown()) then
  68.         return ;
  69.     end
  70.  
  71.     if (not coords.mapId) then
  72.         return ;
  73.     end
  74.  
  75.     local rects = coords.MapRects[coords.mapId];
  76.  
  77.     if (not rects) then
  78.         rects = {};
  79.  
  80.         local _, topLeft = C_Map.GetWorldPosFromMapPos(coords.mapId, CreateVector2D(0, 0));
  81.         local _, bottomRight = C_Map.GetWorldPosFromMapPos(coords.mapId, CreateVector2D(1, 1));
  82.  
  83.         bottomRight:Subtract(topLeft);
  84.  
  85.         rects = { topLeft.x, topLeft.y, bottomRight.x, bottomRight.y };
  86.  
  87.         coords.MapRects[coords.mapId] = rects;
  88.     end
  89.  
  90.     local x, y = UnitPosition("player");
  91.  
  92.     if (x) then
  93.         x = x - rects[1];
  94.         y = y - rects[2];
  95.         x = x / rects[3];
  96.         y = y / rects[4];
  97.         y = y * 100;
  98.         x = x * 100;
  99.  
  100.         coords.text:SetFormattedText("%.1f, %.1f", y, x);
  101.     end
  102. end
  Reply With Quote
07-11-19, 04:42 PM   #11
Kanegasi
A Molten Giant
 
Kanegasi's Avatar
AddOn Author - Click to view addons
Join Date: Apr 2007
Posts: 666
Originally Posted by Terenna View Post
I've been coding my UI casually for ~ 6 years. Turns out I'm still garbage at it compared to you all. It's incredible how absolutely complex you can get to squeeze every inch out of CPU/RAM if you sit down and really go for it.
I feel it's important to point out that RAM usage is not a performance issue, except for leak cases such as this thread you created or playing WoW with less than 8GB of RAM. Many addons, "Details" being a great example, save on a lot of CPU by caching as much info as possible.

CPU will always be WoW's bottleneck. Do not be afraid to cache as much data as possible instead of querying the API. The less you do each frame, especially in combat, the better.
  Reply With Quote
07-12-19, 10:40 AM   #12
kurapica.igas
A Chromatic Dragonspawn
Join Date: Aug 2011
Posts: 152
Originally Posted by Kanegasi View Post
I feel it's important to point out that RAM usage is not a performance issue, except for leak cases such as this thread you created or playing WoW with less than 8GB of RAM. Many addons, "Details" being a great example, save on a lot of CPU by caching as much info as possible.

CPU will always be WoW's bottleneck. Do not be afraid to cache as much data as possible instead of querying the API. The less you do each frame, especially in combat, the better.
In my addon Scorpio, I try to solve the performance problem not by less operations, but with a task schedule system to smoothing the operations like

Lua Code:
  1. Scorpio "TestBigLoop" ""
  2.  
  3. __Async__()
  4. function LongLoop()
  5.     local time = GetTime()
  6.     local prev = 0
  7.  
  8.     for i = 1, 10^7 do
  9.         if i%10 == 0 then
  10.             Continue() -- The frame will freeze if miss this
  11.  
  12.             if time ~= GetTime() then
  13.                 -- Means the thread is resumed in the next frame through OnUpdate
  14.                 time = GetTime()
  15.  
  16.                 -- Here is the current time and the cycle count of the previous phase
  17.                 print(time, i - prev)
  18.                 prev = i
  19.             end
  20.         end
  21.     end
  22. end
  23.  
  24. LongLoop()

The function LongLoop will be processed in a coroutine, and the Continue method will yield it if there is no more time for tasks in the same frame and resume it in the next frame if there is enough time.

This is how the script runs in my old laptop(i5-3230M), I changed a setting to keep the fps to 60, so for one frame the loop will be processed for 2k6-4k times, with the task schedule system I can smooth all my addons to keep the high fps(for my old hardware).

Click image for larger version

Name:	test.jpg
Views:	242
Size:	91.9 KB
ID:	9251

Besides the Continue, there are many others like Wait to wait for several system events, so for me, I can re-code Terenna's code like :

Lua Code:
  1. Scorpio "ShowPosition" ""
  2.  
  3. tCoordsFrame = UIParent:CreateFontString(nil, "OVERLAY", "GameFontNormal")
  4. tCoordsFrame:SetPoint("CENTER")
  5.  
  6. __Async__()
  7. function RefreshPosition()
  8.     local GetBestMapForUnit     = C_Map.GetBestMapForUnit  
  9.     local MapRects              = {}
  10.     local UnitPosition          = UnitPosition
  11.     local GetWorldPosFromMapPos = C_Map.GetWorldPosFromMapPos
  12.     local CreateVector2D        = CreateVector2D
  13.  
  14.     while true do
  15.         if IsPlayerMoving() then
  16.             local mapID         = GetBestMapForUnit('player')
  17.  
  18.             local x, y          = UnitPosition('player')
  19.             if x and mapID then
  20.                 local rects     = MapRects[mapID]
  21.                 if not rects then
  22.                     local _, topleft        = GetWorldPosFromMapPos(mapID, CreateVector2D(0,0))
  23.                     local _, bottomright    = GetWorldPosFromMapPos(mapID, CreateVector2D(1,1))
  24.          
  25.                     bottomright:Subtract(topleft)
  26.                     rects = { topleft.x, topleft.y, bottomright.x, bottomright.y }
  27.                     MapRects[mapID]         = rects
  28.                 end
  29.                
  30.                 x, y = x - rects[1], y - rects[2]
  31.                 x, y = y / rects[4], x / rects[3]
  32.  
  33.                 tCoordsFrame:SetFormattedText('%.1f, %.1f', x * 100, y * 100)
  34.  
  35.                 Delay(0.5)   -- wait 0.5 sec
  36.             else
  37.                 tCoordsFrame:SetText("")
  38.                 -- wait player change zone
  39.                 Wait("PLAYER_ENTERING_WORLD", "ZONE_CHANGED", "ZONE_CHANGED_INDOORS")
  40.             end
  41.         else
  42.             Wait("PLAYER_STARTED_MOVING") -- wait player move
  43.         end
  44.     end
  45. end
  46.  
  47. RefreshPosition()

Although I need more codes(include the framework) to do the same operations, we still can gain better performance through carefully coroutine controls.

Last edited by kurapica.igas : 07-12-19 at 10:44 AM.
  Reply With Quote
07-21-19, 06:58 AM   #13
wildcard25
An Aku'mai Servant
 
wildcard25's Avatar
AddOn Author - Click to view addons
Join Date: Jan 2012
Posts: 30
Originally Posted by Terenna View Post
Lua Code:
  1. local function OnUpdate(self, elapsed, x, y)
  2.     self.elapsed = self.elapsed + elapsed
  3.     while self.elapsed > 0.5 do --only update the coords 2/second
  4.         if mapID then
  5.             x, y = GetPlayerMapPosition(mapID, 'player')
  6.             if x then
  7.                 self.text:SetFormattedText('%.1f, %.1f', x * 100, y * 100)
  8.             else
  9.                 self.text:SetText('')
  10.             end
  11.         end
  12.  
  13.         self.elapsed = self.elapsed - 0.5
  14.     end
  15. end
I'd probably only update the co-ordinates once in the OnUpdate function, then wait for at least another half a second before doing it again. Currently this keeps recalculating the same thing until it gets the elapsed time under half a second. If the pc is already under enough load that more than 1 second has passed between frames, then this would just be adding to the work load.
Lua Code:
  1. local function OnUpdate(self, elapsed, x, y)
  2.     self.elapsed = (self.elapsed or 0) + elapsed
  3.     if self.elapsed > 0.5 then --only update the coords 2/second
  4.         if mapID then
  5.             x, y = GetPlayerMapPosition(mapID, 'player')
  6.             if x then
  7.                 self.text:SetFormattedText('%.1f, %.1f', x * 100, y * 100)
  8.             else
  9.                 self.text:SetText('')
  10.             end
  11.         end
  12.  
  13.         self.elapsed = 0
  14.     end
  15. end
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Minimap Coordinates Memory Usage Optimization

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