This commit is contained in:
陈思海 2026-03-16 20:52:55 +08:00
parent a99b71b049
commit c692b47a62
5 changed files with 9 additions and 45 deletions

View File

@ -26,13 +26,13 @@ namespace AlicizaX
public bool IsRunning;
public bool IsUnscaled;
public bool IsActive;
public byte HandlerType; // 0=Handler, 1=NoArgs, 2=Generic
public byte HandlerType;
public object[] Args;
public object GenericArg;
// 优化1: 添加层级信息,用于精确定位
public int Level; // 当前所在的时间轮层级
public int Level;
public int SlotIndex;
public int NextTimerIndex;
public int PrevTimerIndex;
@ -68,7 +68,6 @@ namespace AlicizaX
private int[] _freeIndices;
private int _freeCount;
// 优化2: 延迟删除队列,避免在遍历时修改链表
private int[] _pendingRemoveTimers;
private int _pendingRemoveCount;
@ -137,7 +136,6 @@ namespace AlicizaX
slotIndex = (_levels[2].CurrentSlot + level2Slots) % SLOT_COUNT_LEVEL2;
}
// 优化3: 记录层级信息
timer.Level = level;
timer.SlotIndex = slotIndex;
timer.NextTimerIndex = _levels[level].SlotHeads[slotIndex];
@ -183,30 +181,26 @@ namespace AlicizaX
wheelLevel.CurrentSlot = (wheelLevel.CurrentSlot + 1) % wheelLevel.SlotCount;
int currentHead = wheelLevel.SlotHeads[wheelLevel.CurrentSlot];
wheelLevel.SlotHeads[wheelLevel.CurrentSlot] = -1; // 清空槽
wheelLevel.SlotHeads[wheelLevel.CurrentSlot] = -1;
// 优化4: 遍历时先断开链表,避免在回调中修改导致问题
int currentIndex = currentHead;
while (currentIndex != -1)
{
ref TimerInfo timer = ref pool[currentIndex];
int nextIndex = timer.NextTimerIndex;
// 断开链表连接
timer.NextTimerIndex = -1;
timer.PrevTimerIndex = -1;
timer.Level = -1; // 标记为不在时间轮中
timer.Level = -1;
if (timer.IsActive && timer.IsRunning)
{
if (level == 0)
{
// Level 0 直接触发
processTimer(currentIndex);
}
else
{
// 高层级降级到低层级
AddTimer(currentIndex, pool, _currentTime);
}
}
@ -215,7 +209,6 @@ namespace AlicizaX
}
}
// 优化5: 安全的移除方法,检查边界
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void RemoveTimer(int poolIndex, TimerInfo[] pool)
{
@ -224,18 +217,15 @@ namespace AlicizaX
ref TimerInfo timer = ref pool[poolIndex];
// 优化6: 如果已经不在时间轮中,直接返回
if (timer.Level < 0 || timer.Level >= _levels.Length)
return;
int level = timer.Level;
int slotIndex = timer.SlotIndex;
// 边界检查
if (slotIndex < 0 || slotIndex >= _levels[level].SlotCount)
return;
// 从链表中移除
if (timer.PrevTimerIndex != -1)
{
if (timer.PrevTimerIndex < pool.Length)
@ -245,7 +235,6 @@ namespace AlicizaX
}
else
{
// 是头节点
_levels[level].SlotHeads[slotIndex] = timer.NextTimerIndex;
}
@ -257,7 +246,6 @@ namespace AlicizaX
}
}
// 清除链表信息
timer.Level = -1;
timer.SlotIndex = -1;
timer.NextTimerIndex = -1;
@ -446,11 +434,9 @@ namespace AlicizaX
ref TimerInfo timer = ref _timerPool[poolIndex];
// 先从时间轮中移除
HierarchicalTimeWheel targetWheel = timer.IsUnscaled ? _unscaledTimeWheel : _scaledTimeWheel;
targetWheel.RemoveTimer(poolIndex, _timerPool);
// 重新计算触发时间并添加
timer.TriggerTime = (timer.IsUnscaled ? Time.unscaledTime : Time.time) + timer.Interval;
targetWheel.AddTimer(poolIndex, _timerPool, timer.IsUnscaled ? Time.unscaledTime : Time.time);
}
@ -464,7 +450,6 @@ namespace AlicizaX
ref TimerInfo timer = ref _timerPool[poolIndex];
timer.IsActive = false;
// 优化7: 只有在时间轮中时才移除
if (timer.Level >= 0)
{
HierarchicalTimeWheel targetWheel = timer.IsUnscaled ? _unscaledTimeWheel : _scaledTimeWheel;
@ -507,7 +492,6 @@ namespace AlicizaX
_scaledTimeWheel.Advance(Time.time, _timerPool, ProcessTimer);
_unscaledTimeWheel.Advance(Time.unscaledTime, _timerPool, ProcessTimer);
// 优化8: 处理延迟删除队列
ProcessPendingRemovals();
}
@ -541,7 +525,6 @@ namespace AlicizaX
Log.Error($"Timer callback error: {e}");
}
// 优化9: 回调后检查是否仍然有效
if (!timer.IsActive)
return;
@ -553,7 +536,6 @@ namespace AlicizaX
}
else
{
// 优化10: 延迟删除,避免在遍历时修改
AddPendingRemoval(timer.TimerId);
}
}

View File

@ -144,7 +144,6 @@ namespace AlicizaX.UI.Runtime
ref var layer = ref _openUI[meta.MetaInfo.UILayer];
int lastIdx = layer.OrderList.Count - 1;
// O(1) lookup instead of O(n) IndexOf
if (!layer.IndexMap.TryGetValue(meta.MetaInfo.RuntimeTypeHandle, out int currentIdx))
return;
@ -153,17 +152,14 @@ namespace AlicizaX.UI.Runtime
layer.OrderList.RemoveAt(currentIdx);
layer.OrderList.Add(meta);
// Update indices for shifted elements
for (int i = currentIdx; i < lastIdx; i++)
{
var m = layer.OrderList[i];
layer.IndexMap[m.MetaInfo.RuntimeTypeHandle] = i;
}
// Update moved element's index
layer.IndexMap[meta.MetaInfo.RuntimeTypeHandle] = lastIdx;
// Only update depth for affected windows (from currentIdx onwards)
SortWindowDepth(meta.MetaInfo.UILayer, currentIdx);
}
}
@ -186,7 +182,6 @@ namespace AlicizaX.UI.Runtime
var list = _openUI[layer].OrderList;
int count = list.Count;
// Find topmost fullscreen window (early exit optimization)
int fullscreenIdx = -1;
for (int i = count - 1; i >= 0; i--)
{
@ -194,14 +189,12 @@ namespace AlicizaX.UI.Runtime
if (meta.MetaInfo.FullScreen && meta.State == UIState.Opened)
{
fullscreenIdx = i;
break; // Early exit - found topmost fullscreen
break;
}
}
// Set visibility based on fullscreen index
if (fullscreenIdx == -1)
{
// No fullscreen window, all visible
for (int i = 0; i < count; i++)
{
list[i].View.Visible = true;
@ -209,7 +202,6 @@ namespace AlicizaX.UI.Runtime
}
else
{
// Hide windows below fullscreen, show from fullscreen onwards
for (int i = 0; i < count; i++)
{
list[i].View.Visible = (i >= fullscreenIdx);
@ -222,12 +214,10 @@ namespace AlicizaX.UI.Runtime
var list = _openUI[layer].OrderList;
int baseDepth = layer * LAYER_DEEP;
// Only update from startIndex onwards (optimization for partial updates)
for (int i = startIndex; i < list.Count; i++)
{
int newDepth = baseDepth + i * WINDOW_DEEP;
// Only set if changed to avoid unnecessary Canvas updates
if (list[i].View.Depth != newDepth)
{
list[i].View.Depth = newDepth;

View File

@ -12,11 +12,10 @@ namespace AlicizaX.UI.Runtime
public abstract partial class UIBase
{
private readonly Dictionary<UIBase, UIMetadata> _children = new();
private readonly List<UIMetadata> _updateableChildren = new(); // Cache for widgets that need updates
private readonly List<UIMetadata> _updateableChildren = new();
private void UpdateChildren()
{
// Use cached list to avoid dictionary enumeration allocation
for (int i = 0; i < _updateableChildren.Count; i++)
{
var meta = _updateableChildren[i];
@ -33,7 +32,6 @@ namespace AlicizaX.UI.Runtime
try
{
int i = 0;
// Use struct enumerator to avoid allocation
foreach (var kvp in _children)
{
temp[i++] = kvp.Value;
@ -56,7 +54,6 @@ namespace AlicizaX.UI.Runtime
private void ChildVisible(bool value)
{
// Use struct enumerator to avoid allocation
foreach (var kvp in _children)
{
var view = kvp.Value.View;
@ -164,7 +161,6 @@ namespace AlicizaX.UI.Runtime
return false;
}
// Add to updateable list if widget needs updates
if (meta.MetaInfo.NeedUpdate)
{
_updateableChildren.Add(meta);
@ -180,7 +176,6 @@ namespace AlicizaX.UI.Runtime
meta.CancelAsyncOperations();
await widget.InternalClose();
// Remove from updateable list if present
if (meta.MetaInfo.NeedUpdate)
{
_updateableChildren.Remove(meta);

View File

@ -233,7 +233,7 @@ namespace AlicizaX.UI.Runtime
internal async UniTask InternalClose(CancellationToken cancellationToken = default)
{
if (_state != UIState.Opened)
return; // Not open, nothing to close
return;
if (!UIStateMachine.ValidateTransition(GetType().Name, _state, UIState.Closed))
return;

View File

@ -68,10 +68,7 @@ namespace AlicizaX.UI.Runtime
private bool _isAlive = true;
/// <summary>
/// Checks if this holder is still valid (not destroyed).
/// Use this instead of null check for better clarity.
/// </summary>
public bool IsValid()
{
return this != null && _isAlive;