perf: reduce CPU hotspots identified in profiler
- HBD.lua: Cache GetPlayerWorldPosition/GetPlayerZonePosition at 50ms
intervals instead of hammering GetPlayerMapPosition() every frame.
Invalidate cache on PLAYER_ENTERING_WORLD and ZONE_CHANGED_* events.
Expected ~97% reduction in C API position calls (45,570 -> ~1,200 / 10min).
- zoneDB.lua: Replace O(n) linear scan in GetAreaIdByUiMapId with an
O(1) reverse lookup cache (uiMapIdToAreaIdCache) built at Initialize().
Cache is kept in sync by ApplyCustomZones and name-match fallback now
caches its result so subsequent calls are also O(1).
- Tooltip.lua: Throttle GameTooltip OnUpdate hook to 100ms intervals
(was firing every frame at 60-144 Hz). Added _tooltipLastText cache
to avoid redundant GetText() + CountTooltip() calls when nothing changed.
- QuestieArrow.lua: Hoist _HasMissingCompletedFlag, _GetCompleteIconType,
_CollectFinisherSpawns, and _CollectObjective out of _CollectQuestTargets
to module-level functions. These were re-created as closures on every
UpdateNearestTargets call (1 Hz). Shared per-cycle context is published
via _arrow_* module upvalues to avoid closure capture overhead.
- QuestieLearnerComms.lua: Four micro-optimizations:
(1) Reduce ProcessQueues ticker 0.2s -> 0.5s (still 7x faster than
minChatInterval of 3.5s).
(2) Cache hidden channel ID at init; lazy refresh on disconnect.
(3) Drop LibDeflate compress level 9 -> 1 (fraction of CPU cost).
(4) O(1) messageCacheCount counter replaces O(n) pairs() size scan.
This commit is contained in:
+36
-6
@@ -95,16 +95,33 @@ function HBD:GetZoneDistance(oZone, oX, oY, dZone, dX, dY)
|
||||
return self:GetWorldDistance(oInstance, oX, oY, dX, dY)
|
||||
end
|
||||
|
||||
-- Position cache: avoid hammering the C API more than 20 times per second.
|
||||
-- These are invalidated on zone-change events below.
|
||||
local _pos_cache_interval = 0.05
|
||||
local _pzp_x, _pzp_y, _pzp_mapID, _pzp_time = nil, nil, nil, 0
|
||||
local _pwp_x, _pwp_y, _pwp_inst, _pwp_time = nil, nil, nil, 0
|
||||
|
||||
--- Get the current world position of the player
|
||||
-- The position is transformed to the current continent, if applicable
|
||||
-- @return x, y, instanceID
|
||||
function HBD:GetPlayerWorldPosition()
|
||||
local x, y, uiMapID = HBD:GetPlayerZonePosition()
|
||||
if not x or not y then return nil, nil, nil end
|
||||
local now = GetTime()
|
||||
if now - _pwp_time < _pos_cache_interval then
|
||||
return _pwp_x, _pwp_y, _pwp_inst
|
||||
end
|
||||
|
||||
x, y, instanceID = HBD:GetWorldCoordinatesFromZone(x, y, uiMapID)
|
||||
if x and y then
|
||||
return x, y, instanceID
|
||||
local x, y, uiMapID = HBD:GetPlayerZonePosition()
|
||||
if not x or not y then
|
||||
_pwp_x, _pwp_y, _pwp_inst = nil, nil, nil
|
||||
_pwp_time = now
|
||||
return nil, nil, nil
|
||||
end
|
||||
|
||||
local wx, wy, inst = HBD:GetWorldCoordinatesFromZone(x, y, uiMapID)
|
||||
_pwp_x, _pwp_y, _pwp_inst = wx, wy, inst
|
||||
_pwp_time = now
|
||||
if wx and wy then
|
||||
return wx, wy, inst
|
||||
end
|
||||
return nil, nil, nil
|
||||
end
|
||||
@@ -121,8 +138,14 @@ end
|
||||
-- @param allowOutOfBounds Allow coordinates to go beyond the current map (ie. outside of the 0-1 range), otherwise nil will be returned
|
||||
-- @return x, y, uiMapID, mapType
|
||||
function HBD:GetPlayerZonePosition(allowOutOfBounds)
|
||||
-- get the current position
|
||||
local now = GetTime()
|
||||
if now - _pzp_time < _pos_cache_interval then
|
||||
return _pzp_x, _pzp_y, _pzp_mapID
|
||||
end
|
||||
|
||||
local uiMapID, x, y = QuestieCompat.GetCurrentPlayerPosition()
|
||||
_pzp_x, _pzp_y, _pzp_mapID = x, y, uiMapID
|
||||
_pzp_time = now
|
||||
|
||||
if uiMapID and x and y then
|
||||
return x, y, uiMapID
|
||||
@@ -130,6 +153,11 @@ function HBD:GetPlayerZonePosition(allowOutOfBounds)
|
||||
return nil, nil, nil, nil
|
||||
end
|
||||
|
||||
local function _InvalidatePositionCache()
|
||||
_pzp_time = 0
|
||||
_pwp_time = 0
|
||||
end
|
||||
|
||||
-- Data Constants
|
||||
local WORLD_MAP_ID = 947
|
||||
|
||||
@@ -598,11 +626,13 @@ local function OnEventHandler(frame, event, ...)
|
||||
-- recheck cvars after login
|
||||
rotateMinimap = GetCVar("rotateMinimap") == "1"
|
||||
elseif event == "PLAYER_ENTERING_WORLD" then
|
||||
_InvalidatePositionCache()
|
||||
UpdateMinimap()
|
||||
UpdateWorldMap()
|
||||
elseif event == "WORLD_MAP_UPDATE" then
|
||||
UpdateWorldMap()
|
||||
elseif string.find(event, "ZONE_CHANGED") then
|
||||
_InvalidatePositionCache()
|
||||
UpdateMinimap()
|
||||
UpdateWorldMap()
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user