Skip to content

Commit 8ccbd17

Browse files
Optimize Count(), fix debug assert, and fix SetExpiration cleanup
- Count(): fast-path when no expirations are due yet (peek min), iterate RawHeap instead of sortedSetDict for expired count - Add RawHeap property to IndexedPriorityQueue for fast iteration - Fix Debug.Assert to use correct minimum (SortedSetOverhead + DictionaryOverhead) - Fix SetExpiration: remove from expirationQueue when expiration is in the past Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 81ac050 commit 8ccbd17

2 files changed

Lines changed: 14 additions & 4 deletions

File tree

libs/common/Collections/IndexedPriorityQueue.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ public class IndexedPriorityQueue<TElement, TPriority>
2222
private (TElement element, TPriority priority)[] _heap = [];
2323
private int _count;
2424

25+
/// <summary>
26+
/// Raw heap access to do iteration really fast
27+
/// </summary>
28+
public (TElement element, TPriority priority)[] RawHeap => _heap;
29+
2530
/// <summary>
2631
/// Number of elements in the priority queue.
2732
/// </summary>

libs/server/Objects/SortedSet/SortedSetObject.cs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -571,14 +571,18 @@ public bool TryGetScore(byte[] key, out double value)
571571
/// <returns>The count of elements in the sorted set.</returns>
572572
public int Count()
573573
{
574-
if (!HasExpirableItems())
574+
if (!HasExpirableItems() || (expirationQueue.TryPeek(out _, out var minExpiration) && minExpiration > DateTimeOffset.UtcNow.Ticks))
575575
return sortedSetDict.Count;
576576

577577
var expiredKeysCount = 0;
578-
foreach (var item in sortedSetDict)
578+
var rawHeap = expirationQueue.RawHeap;
579+
var heapCount = expirationQueue.Count;
580+
for (int i = 0; i < heapCount; i++)
579581
{
580-
if (IsExpired(item.Key))
582+
if (rawHeap[i].priority < DateTimeOffset.UtcNow.Ticks)
583+
{
581584
expiredKeysCount++;
585+
}
582586
}
583587
return sortedSetDict.Count - expiredKeysCount;
584588
}
@@ -616,7 +620,7 @@ private void UpdateExpirationSize(bool add)
616620
else
617621
{
618622
HeapMemorySize -= MemoryUtils.IndexedPriorityQueueEntryOverhead;
619-
Debug.Assert(HeapMemorySize >= MemoryUtils.DictionaryOverhead);
623+
Debug.Assert(HeapMemorySize >= MemoryUtils.DictionaryOverhead + MemoryUtils.SortedSetOverhead);
620624
}
621625
}
622626

@@ -669,6 +673,7 @@ private int SetExpiration(byte[] key, long expiration, ExpireOption expireOption
669673
{
670674
_ = sortedSetDict.Remove(key, out var value);
671675
_ = sortedSet.Remove((value, key));
676+
_ = expirationQueue.TryRemove(key);
672677
UpdateSize(key, add: false);
673678
return (int)SortedSetExpireResult.KeyAlreadyExpired;
674679
}

0 commit comments

Comments
 (0)