Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: cache GUIDs without any unit IDs mappings for later removal #972

Merged
merged 1 commit into from
Aug 30, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 32 additions & 2 deletions src/engine/guid.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import aceEvent, { AceEvent } from "@wowts/ace_event-3.0";
import { LuaArray, LuaObj, ipairs, lualength, pairs, unpack } from "@wowts/lua";
import { concat, insert } from "@wowts/table";
import { concat, insert, sort } from "@wowts/table";
import { GetUnitName, UnitGUID, UnitIsUnit } from "@wowts/wow-mock";
import { AceModule } from "@wowts/tsaddon";
import { OvaleClass } from "../Ovale";
import { Tracer, DebugTools } from "./debug";
import { binaryInsertUnique, binaryRemove } from "../tools/array";
import { LRUCache } from "../tools/cache";
import { OptionUiGroup } from "../ui/acegui-helpers";

function dumpMapping(t: LuaObj<LuaArray<string>>, output: LuaArray<string>) {
Expand Down Expand Up @@ -34,15 +35,16 @@ export class Guids {
private nameByGUID: LuaObj<string> = {};
private guidByName: LuaObj<LuaArray<string>> = {};
private ownerGUIDByGUID: LuaObj<string> = {};
private unusedGUIDCache: LRUCache<string>;

private childUnitByUnit: LuaObj<LuaObj<boolean>> = {};
private petUnitByUnit: LuaObj<string> = {};

// eventfulUnits is an ordered array of unit IDs that receive unit events.
private eventfulUnits: LuaArray<string> = {};
private unitPriority: LuaObj<number> = {};
unitAuraUnits: LuaObj<boolean> = {};

unitAuraUnits: LuaObj<boolean> = {};
petGUID: LuaObj<boolean> = {};

private debugGUIDs: OptionUiGroup = {
Expand All @@ -64,6 +66,13 @@ export class Guids {
insert(output, "}\n");
insert(output, "GUID by Name = {");
dumpMapping(this.guidByName, output);
insert(output, "}\n");
insert(output, "Unused GUIDs = {");
const guids = this.unusedGUIDCache.asArray();
sort(guids);
for (const [, guid] of ipairs(guids)) {
insert(output, ` ${guid}`);
}
insert(output, "}");
return concat(output, "\n");
},
Expand All @@ -81,6 +90,10 @@ export class Guids {
aceEvent
);
this.tracer = debug.create(this.module.GetName());
/* Cache the last 100 unreferenced GUIDs to retain their
* name mappings.
*/
this.unusedGUIDCache = new LRUCache<string>(100);

this.petUnitByUnit["player"] = "pet";
insert(this.eventfulUnits, "player");
Expand Down Expand Up @@ -343,6 +356,8 @@ export class Guids {
const t = this.unitByGUID[guid] || {};
binaryInsertUnique(t, unit, this.compareUnit);
this.unitByGUID[guid] = t;
// This GUID has a unit ID, so remove it from the cache.
this.unusedGUIDCache.remove(guid);
};

private unmapGUIDToUnit = (guid: string, unit: string) => {
Expand All @@ -352,6 +367,21 @@ export class Guids {
binaryRemove(t, unit, this.compareUnit);
if (lualength(t) == 0) {
delete this.unitByGUID[unit];

/* This GUID has no more unit IDs associated with it, so
* put it the cache for eventual garbage collection.
*/
const evictedGUID = this.unusedGUIDCache.put(guid);
// Garbage-collect mappings for GUID evicted from cache.
if (evictedGUID) {
const name = this.nameByGUID[evictedGUID];
if (name) {
this.unmapNameToGUID(name, evictedGUID);
}
delete this.ownerGUIDByGUID[evictedGUID];
delete this.petGUID[evictedGUID];
this.module.SendMessage("Ovale_UnusedGUID", evictedGUID);
}
}
}
};
Expand Down