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:
Xurkon
2026-03-29 16:42:43 -05:00
parent 2d9d83f265
commit 05ea31bc53
5 changed files with 288 additions and 142 deletions
+36 -6
View File
@@ -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