Skip to content

Commit

Permalink
Improved add-on performance, especially when using GDKP queues
Browse files Browse the repository at this point in the history
  • Loading branch information
papa-smurf committed May 12, 2023
1 parent 731105e commit f550ea0
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 15 deletions.
50 changes: 48 additions & 2 deletions Classes/Comm.lua
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ function Comm:_init()
-- Register the Ace Comm channel listener
GL.Ace:RegisterComm(self.channel, Comm.listen);

-- Store the default ChatThrottleLib burst and CPS values
self.defaultBurstValue = _G.ChatThrottleLib.BURST or 4000;
self.defaultCPSValue = _G.ChatThrottleLib.MAX_CPS or 800;

self._initialized = true;
end

Expand All @@ -125,6 +129,7 @@ function Comm:send(CommMessage, broadcastFinishedCallback, packageSentCallback)

local distribution = CommMessage.channel;
local recipient = CommMessage.recipient;
local action = CommMessage.action;

if (distribution == "GROUP") then
distribution = "PARTY";
Expand Down Expand Up @@ -156,23 +161,64 @@ function Comm:send(CommMessage, broadcastFinishedCallback, packageSentCallback)
end

-- We lower the burst value and cps on large payloads to make sure
-- our messages are not dropped by the server, which happens A LOT ffs
-- our messages are not dropped by the server. ChatThrottleLib is not accurate enough sadly
local stringLength = string.len(compressedMessage);
GL:debug("Payload size: " .. stringLength);
local throttle = distribution ~= "WHISPER" and stringLength > 1900;

local throttleResetTimer;
-- Stop throttling: reset the burst and max cps values
local stopThrottling = function()
GL:debug("Resetting burst value and cps");

_G.ChatThrottleLib.BURST = self.defaultBurstValue;
_G.ChatThrottleLib.MAX_CPS = self.defaultCPSValue;
end;

if (throttle) then
GL:debug("Throttling burst value and cps");

_G.ChatThrottleLib.BURST = 2000;
_G.ChatThrottleLib.MAX_CPS = 400;

-- Make sure we reset the values even if the message couldn't be sent
throttleResetTimer = GL.Ace:ScheduleTimer(function ()
stopThrottling();
end, 5);
end

-- Make sure we can keep an eye on comm behavior
if (GL.User:isDev()) then
local actionTitle = GL:tableFlip(Actions)[action] or action;
DevTools_Dump(("Action: %s | Payload size: %s | Throttled: %s"):format(tostring(actionTitle), stringLength, throttle and "Y" or "N"));
end

GL.Ace:SendCommMessage(self.channel, compressedMessage, distribution, recipient, "BULK", function (_, sent, textlen)
GL:debug(string.format("Sent %s from %s characters", sent, textlen));

-- Cancel the throttle reset timer if it exists
if (throttleResetTimer) then
GL.Ace:CancelTimer(throttleResetTimer);
end

-- Execute the package sent calback
if (type(packageSentCallback) == "function") then
packageSentCallback(sent, textlen);
end

if (sent >= textlen) then
if (throttle) then
stopThrottling();
end

-- Execute the broadcast finished callback
if (type(broadcastFinishedCallback) == "function") then
broadcastFinishedCallback(sent, textlen);
end
else
-- Make sure we reset the values even if the message couldn't be sent in full
throttleResetTimer = GL.Ace:ScheduleTimer(function ()
stopThrottling();
end, 5);
end
end);
end
Expand Down
2 changes: 1 addition & 1 deletion Classes/CommMessage.lua
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ function CommMessage:compress(Message)

local success, encoded = pcall(function ()
local serialized = LibSerialize:Serialize(Payload);
local compressed = LibDeflate:CompressDeflate(serialized, {level = 8});
local compressed = LibDeflate:CompressDeflate(serialized, {level = 5});
local encoded = LibDeflate:EncodeForWoWAddonChannel(compressed);

return encoded;
Expand Down
105 changes: 94 additions & 11 deletions Classes/GDKP/Auction.lua
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ local Auctioneer;

---@class GDKPAuction
GDKP.Auction = {
_broadcastingDisabled = false,
_initialized = false,
autoBiddingIsActive = nil,
lastBidAt = nil,
Expand Down Expand Up @@ -65,7 +66,7 @@ local GDKPSession = GDKP.Session;

--[[ CONSTANTS ]]
local AUTO_BID_THROTTLE_IN_SECONDS = .6;
local BROADCAST_QUEUE_DELAY_IN_SECONDS = 2;
local BROADCAST_QUEUE_DELAY_IN_SECONDS = 3;

function Auction:_init()
GL:debug("GDKP.Auction:_init");
Expand Down Expand Up @@ -130,6 +131,7 @@ function Auction:_initializeQueue()
return;
end

self._broadcastingDisabled = true;
local SortedQueue = GL:tableValues(Auction.Queue);
table.sort(SortedQueue, function (a, b)
if (a.order and b.order) then
Expand All @@ -151,13 +153,21 @@ function Auction:_initializeQueue()
GL.Ace:CancelTimer(QueueAddTimer);
SortedQueue = nil;

self._broadcastingDisabled = false;

GL.Events:fire("GL.GDKP_QUEUE_UPDATED");

-- Make sure to broadcast the queue when everything's said and done
if (i > 1) then
self:broadcastQueue();
end

return;
end

i = i + 1;
return Auctioneer:addToQueue(Queued.itemLink, Queued.identifier, false);
end, .2);
end, .1);
end

---@return void
Expand Down Expand Up @@ -830,10 +840,8 @@ function Auction:addToQueue(itemLink, identifier)
return;
end

local addedAt = GetTime();
local PerItemSettings = GDKP:settingsForItemID(GL:getItemIDFromLink(itemLink));
self.Queue[identifier] = {
addedAt = addedAt,
identifier = identifier,
increment = PerItemSettings.increment,
itemID = itemID,
Expand Down Expand Up @@ -918,8 +926,7 @@ end
function Auction:removeFromQueue(checksum)
GL:debug("Auction:removeFromQueue");

checksum = tostring(checksum or 0);
if (not self.Queue[checksum]) then
if (not self.Queue[checksum or 0]) then
return false;
end

Expand Down Expand Up @@ -978,21 +985,58 @@ function Auction:sanitizeQueue()
end
end

--- Broadcast the first 20 items to everyone in the raid
---@return void
function Auction:broadcastQueue(immediately)
GL:debug("Auction:broadcastQueue");

-- Broadcasting is
if (self._broadcastingDisabled) then
return;
end

GL.Ace:CancelTimer(self.QueueBroadcastTimer);
self:sanitizeQueue();

if (not Auctioneer:allowedToBroadcast()) then
return;
end

-- Make sure we only broadcast the first 15 items as to not overload the system
local SortedQueue = GL:tableValues(Auction.Queue);
table.sort(SortedQueue, function (a, b)
if (a.order and b.order) then
return a.order < b.order;
end

return false;
end);

local QueueSegment = {};
local i = 0;
for _, Details in pairs(SortedQueue) do

i = i + 1;

-- Trim down the queue details in order to minimize the comm payload
tinsert(QueueSegment, {
Details.identifier,
Details.itemID,
Details.minimumBid,
Details.order,
Details.increment,
});

-- A queue of more than a 100 items makes no sense
if (i > 100) then
break;
end
end

local broadcast = function ()
GL.CommMessage.new(
CommActions.broadcastGDKPAuctionQueue,
self.Queue or {},
QueueSegment or {},
"GROUP"
):send();
end;
Expand Down Expand Up @@ -1025,10 +1069,50 @@ function Auction:receiveQueue(CommMessage)
return;
end

self.Queue = CommMessage.content;
self:sanitizeQueue();
local Queue = {};

-- Check if this is the old format including item links
local itemLinksArePresent = true;
for _, Details in pairs(CommMessage.content or {}) do
itemLinksArePresent = not not Details.itemLink;
end

-- Old format, no need to continue
if (itemLinksArePresent) then
self.Queue = Queue;
self:sanitizeQueue();

Events:fire("GL.GDKP_QUEUE_UPDATED");
return;
end

Events:fire("GL.GDKP_QUEUE_UPDATED");
-- Enrich the received queue with required data
GL:onItemLoadDo(GL:tableColumn(CommMessage.content, 2), function (Details)
local ItemLinksByID = {};

for _, Entry in pairs(Details) do
ItemLinksByID[Entry.id] = Entry.link;
end

for _, Queued in pairs(CommMessage.content or {}) do
local itemLink = ItemLinksByID[Queued[2]];
if (itemLink) then
Queue[Queued[1]] = {
identifier = Queued[1],
itemID = Queued[2],
minimumBid = Queued[3],
order = Queued[4],
increment = Queued[5],
itemLink = itemLink,
};
end
end

self.Queue = Queue;
self:sanitizeQueue();

Events:fire("GL.GDKP_QUEUE_UPDATED");
end);
end

--- Announce to everyone in the raid that an auction is starting
Expand Down Expand Up @@ -1080,7 +1164,6 @@ function Auction:announceStart(itemLink, minimumBid, minimumIncrement, duration,

self.inProgress = true;
self:listenForBids();
self:broadcastQueue(true);

-- This is still the same item, use the previous highest bid as the starting point
if (itemLink == self.Current.itemLink) then
Expand Down
2 changes: 1 addition & 1 deletion Classes/GDKP/Auctioneer.lua
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ function Auctioneer:addToQueue(itemLink, identifier, open)
AuctioneerUI = AuctioneerUI or GL.Interface.GDKP.Auctioneer;

local Queue = AuctioneerUI:getQueueWindow(true);
identifier = identifier or GL:stringHash(GetTime() .. itemLink) .. math.random(1, 1000);
identifier = identifier or tonumber(GL:stringHash(GetTime() .. itemLink) .. math.random(1, 1000));

Auction:addToQueue(itemLink, identifier);
Queue:addItemByLink(itemLink, identifier);
Expand Down
1 change: 1 addition & 0 deletions Classes/Helpers.lua
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,7 @@ end
--- StringHash method, courtesy of Mikk38024 @ Wowpedia (https://wowpedia.fandom.com/wiki/StringHash)
---
---@param text string|table
---@return number
function GL:stringHash(text)
if (type(text) == "table") then
text = GL:implode(text, ".");
Expand Down
4 changes: 4 additions & 0 deletions _ide_helper.lua
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ AceGUIIcon = {};
---@class AceGUIButton
AceGUIButton = {};

-- [[ GLOBAL ]]
---@param mixed any
function DevTools_Dump(mixed) end

-- [[ AceGUIFrame ]]
---@param value string
function AceGUIFrame:SetStatusText(value) end
Expand Down

0 comments on commit f550ea0

Please sign in to comment.