Some misc performance changes + logging
This commit is contained in:
@@ -62,6 +62,10 @@ public abstract unsafe class InventoryAddonBase : NativeAddon, IInventoryWindow
|
|||||||
private readonly HashSet<uint> _searchMatchScratch = new();
|
private readonly HashSet<uint> _searchMatchScratch = new();
|
||||||
private bool _isRefreshing;
|
private bool _isRefreshing;
|
||||||
|
|
||||||
|
private int _requestedUpdateCount;
|
||||||
|
private int _refreshFromLifecycleCount;
|
||||||
|
private long _lastLogTick;
|
||||||
|
|
||||||
public void ManualRefresh()
|
public void ManualRefresh()
|
||||||
{
|
{
|
||||||
if (!IsOpen) return;
|
if (!IsOpen) return;
|
||||||
@@ -104,6 +108,10 @@ public abstract unsafe class InventoryAddonBase : NativeAddon, IInventoryWindow
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
_isRefreshing = true;
|
_isRefreshing = true;
|
||||||
|
|
||||||
|
_refreshFromLifecycleCount++;
|
||||||
|
LogRefreshStats();
|
||||||
|
|
||||||
InventoryState.RefreshFromGame();
|
InventoryState.RefreshFromGame();
|
||||||
RefreshCategoriesCore(autosize: true);
|
RefreshCategoriesCore(autosize: true);
|
||||||
}
|
}
|
||||||
@@ -405,8 +413,23 @@ public abstract unsafe class InventoryAddonBase : NativeAddon, IInventoryWindow
|
|||||||
RefreshCategoriesCore(false);
|
RefreshCategoriesCore(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void LogRefreshStats()
|
||||||
|
{
|
||||||
|
long now = Environment.TickCount64;
|
||||||
|
if (now - _lastLogTick > 1000) // Log every second
|
||||||
|
{
|
||||||
|
Services.Logger.DebugOnly($"[Perf] Last 1s: OnRequestedUpdate={_requestedUpdateCount}, RefreshFromLifecycle={_refreshFromLifecycleCount}");
|
||||||
|
_requestedUpdateCount = 0;
|
||||||
|
_refreshFromLifecycleCount = 0;
|
||||||
|
_lastLogTick = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected override void OnRequestedUpdate(AtkUnitBase* addon, NumberArrayData** numberArrayData, StringArrayData** stringArrayData)
|
protected override void OnRequestedUpdate(AtkUnitBase* addon, NumberArrayData** numberArrayData, StringArrayData** stringArrayData)
|
||||||
{
|
{
|
||||||
|
_requestedUpdateCount++;
|
||||||
|
LogRefreshStats();
|
||||||
|
|
||||||
base.OnRequestedUpdate(addon, numberArrayData, stringArrayData);
|
base.OnRequestedUpdate(addon, numberArrayData, stringArrayData);
|
||||||
|
|
||||||
if (DragDropState.IsDragging)
|
if (DragDropState.IsDragging)
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ public static class Util
|
|||||||
{
|
{
|
||||||
FileInfo file = JsonFileHelper.GetFileInfo(SystemConfiguration.FileName);
|
FileInfo file = JsonFileHelper.GetFileInfo(SystemConfiguration.FileName);
|
||||||
var config = JsonFileHelper.LoadFile<SystemConfiguration>(file.FullName);
|
var config = JsonFileHelper.LoadFile<SystemConfiguration>(file.FullName);
|
||||||
config?.EnsureInitialized();
|
config.EnsureInitialized();
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ public sealed unsafe class LootedItemsTracker : IDisposable
|
|||||||
private readonly List<LootedItemInfo> _lootedItems = new(capacity: 64);
|
private readonly List<LootedItemInfo> _lootedItems = new(capacity: 64);
|
||||||
private readonly Dictionary<(uint ItemId, bool IsHq), (InventoryItem Item, int Quantity)> _pendingChanges = new(capacity: 32);
|
private readonly Dictionary<(uint ItemId, bool IsHq), (InventoryItem Item, int Quantity)> _pendingChanges = new(capacity: 32);
|
||||||
|
|
||||||
|
private static HashSet<uint>? _filteredCategoryItems;
|
||||||
|
|
||||||
private bool _isEnabled;
|
private bool _isEnabled;
|
||||||
private long _batchStartTick;
|
private long _batchStartTick;
|
||||||
private bool _hasPendingRemoval;
|
private bool _hasPendingRemoval;
|
||||||
@@ -171,12 +173,18 @@ public sealed unsafe class LootedItemsTracker : IDisposable
|
|||||||
|
|
||||||
private static bool ShouldFilterItem(uint itemId)
|
private static bool ShouldFilterItem(uint itemId)
|
||||||
{
|
{
|
||||||
if (!Services.DataManager.GetExcelSheet<Item>().TryGetRow(itemId, out var item))
|
if (_filteredCategoryItems == null)
|
||||||
return false;
|
{
|
||||||
|
_filteredCategoryItems = new HashSet<uint>();
|
||||||
|
var sheet = Services.DataManager.GetExcelSheet<Item>();
|
||||||
|
foreach (var row in sheet)
|
||||||
|
{
|
||||||
|
if (row.ItemUICategory.RowId == 62)
|
||||||
|
_filteredCategoryItems.Add(row.RowId);
|
||||||
|
}
|
||||||
|
Services.Logger.DebugOnly($"[LootedItemsTracker] Built filter cache with {_filteredCategoryItems.Count} items");
|
||||||
|
}
|
||||||
|
|
||||||
if (item.ItemUICategory.RowId == 62)
|
return _filteredCategoryItems.Contains(itemId);
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using AetherBags.Inventory.Items;
|
using AetherBags.Inventory.Items;
|
||||||
|
using FFXIVClientStructs.FFXIV.Client.Game;
|
||||||
using FFXIVClientStructs.FFXIV.Client.UI;
|
using FFXIVClientStructs.FFXIV.Client.UI;
|
||||||
using FFXIVClientStructs.FFXIV.Common.Math;
|
using FFXIVClientStructs.FFXIV.Common.Math;
|
||||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||||
@@ -42,17 +43,28 @@ public sealed unsafe class LootedItemDisplayNode : SimpleComponentNode
|
|||||||
_quantityTextNode.AttachNode(this);
|
_quantityTextNode.AttachNode(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LootedItemInfo LootedItem
|
public LootedItemInfo? LootedItem
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
bool needsCollisionUpdate = field is null && value is not null;
|
bool needsCollisionUpdate = field is null && value is not null;
|
||||||
field = value;
|
field = value;
|
||||||
var item = value.Item;
|
|
||||||
_iconNode.IconId = item.IconId;
|
if (value is not null)
|
||||||
_iconNode.ItemTooltip = item.ItemId;
|
{
|
||||||
_quantityTextNode.String = value.Quantity > 1 ? value.Quantity.ToString() : string.Empty;
|
InventoryItem item = value.Item;
|
||||||
|
_iconNode.IconId = item.IconId;
|
||||||
|
_iconNode.ItemTooltip = item.ItemId;
|
||||||
|
_quantityTextNode.String = value.Quantity > 1 ? value.Quantity.ToString() : string.Empty;
|
||||||
|
_iconNode.IsVisible = true;
|
||||||
|
_quantityTextNode.IsVisible = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_iconNode.IsVisible = false;
|
||||||
|
_quantityTextNode.String = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
if (needsCollisionUpdate)
|
if (needsCollisionUpdate)
|
||||||
{
|
{
|
||||||
@@ -61,7 +73,7 @@ public sealed unsafe class LootedItemDisplayNode : SimpleComponentNode
|
|||||||
addon->UpdateCollisionNodeList(false);
|
addon->UpdateCollisionNodeList(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} = null!;
|
} = null;
|
||||||
|
|
||||||
private void OnMouseClick(AtkEventListener* thisPtr, AtkEventType eventType, int eventParam, AtkEvent* atkEvent, AtkEventData* atkEventData)
|
private void OnMouseClick(AtkEventListener* thisPtr, AtkEventType eventType, int eventParam, AtkEvent* atkEvent, AtkEventData* atkEventData)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -180,6 +180,7 @@ public abstract class DeferrableLayoutListNode : SimpleComponentNode
|
|||||||
private List<NodeBase>? _desiredScratch;
|
private List<NodeBase>? _desiredScratch;
|
||||||
private List<NodeBase>? _toRemoveScratch;
|
private List<NodeBase>? _toRemoveScratch;
|
||||||
private HashSet<object>? _dataKeysScratch;
|
private HashSet<object>? _dataKeysScratch;
|
||||||
|
private Dictionary<object, NodeBase>? _byKeyScratch;
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private List<NodeBase> RentExistingList(int capacity)
|
private List<NodeBase> RentExistingList(int capacity)
|
||||||
@@ -309,7 +310,16 @@ public abstract class DeferrableLayoutListNode : SimpleComponentNode
|
|||||||
Dictionary<TKey, TU>? byKey = null;
|
Dictionary<TKey, TU>? byKey = null;
|
||||||
if (existing.Count > 0)
|
if (existing.Count > 0)
|
||||||
{
|
{
|
||||||
byKey = new Dictionary<TKey, TU>(existing.Count, keyComparer);
|
if (_byKeyScratch is Dictionary<TKey, TU> reusable)
|
||||||
|
{
|
||||||
|
byKey = reusable;
|
||||||
|
byKey.Clear();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
byKey = new Dictionary<TKey, TU>(existing.Count, keyComparer);
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < existing.Count; i++)
|
for (int i = 0; i < existing.Count; i++)
|
||||||
{
|
{
|
||||||
var tu = (TU)existing[i];
|
var tu = (TU)existing[i];
|
||||||
@@ -407,6 +417,12 @@ public abstract class DeferrableLayoutListNode : SimpleComponentNode
|
|||||||
RecalculateLayout();
|
RecalculateLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (byKey != null)
|
||||||
|
{
|
||||||
|
byKey.Clear();
|
||||||
|
_byKeyScratch = byKey as Dictionary<object, NodeBase>;
|
||||||
|
}
|
||||||
|
|
||||||
return structureChanged || orderChanged;
|
return structureChanged || orderChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user