From 35351eaff1ae7145058dcd05bbb7d36642198527 Mon Sep 17 00:00:00 2001 From: Grisha Kotler Date: Thu, 10 Oct 2024 22:34:56 +0300 Subject: [PATCH] RavenDB-22986 - improve the performance of getting the free pages count --- src/Voron/Impl/FreeSpace/FreeSpaceHandling.cs | 25 +++++++++++++++++++ .../Impl/FreeSpace/IFreeSpaceHandling.cs | 1 + .../Impl/FreeSpace/NoFreeSpaceHandling.cs | 5 ++++ src/Voron/Impl/FreeSpace/StreamBitArray.cs | 13 ++++++++++ 4 files changed, 44 insertions(+) diff --git a/src/Voron/Impl/FreeSpace/FreeSpaceHandling.cs b/src/Voron/Impl/FreeSpace/FreeSpaceHandling.cs index d658b0b48b8b..ecae4358902d 100644 --- a/src/Voron/Impl/FreeSpace/FreeSpaceHandling.cs +++ b/src/Voron/Impl/FreeSpace/FreeSpaceHandling.cs @@ -349,6 +349,31 @@ public List AllPages(LowLevelTransaction tx) } } + public int GetFreePagesCount(LowLevelTransaction tx) + { + var freeSpaceTree = GetFreeSpaceTree(tx); + if (freeSpaceTree.NumberOfEntries == 0) + return 0; + + using (var it = freeSpaceTree.Iterate()) + { + if (it.Seek(0) == false) + return 0; + + var count = 0; + + do + { + var stream = it.CreateReaderForCurrent(); + var current = new StreamBitArray(stream); + count += current.GetNumberOfSetBits(); + + } while (it.MoveNext()); + + return count; + } + } + public void FreePage(LowLevelTransaction tx, long pageNumber) { if (_guard.IsProcessingFixedSizeTree) diff --git a/src/Voron/Impl/FreeSpace/IFreeSpaceHandling.cs b/src/Voron/Impl/FreeSpace/IFreeSpaceHandling.cs index 3515b9e886e4..c7997b85c6cd 100644 --- a/src/Voron/Impl/FreeSpace/IFreeSpaceHandling.cs +++ b/src/Voron/Impl/FreeSpace/IFreeSpaceHandling.cs @@ -6,6 +6,7 @@ public interface IFreeSpaceHandling { long? TryAllocateFromFreeSpace(LowLevelTransaction tx, int num); List AllPages(LowLevelTransaction tx); + int GetFreePagesCount(LowLevelTransaction txLowLevelTransaction); void FreePage(LowLevelTransaction tx, long pageNumber); long GetFreePagesOverhead(LowLevelTransaction tx); IEnumerable GetFreePagesOverheadPages(LowLevelTransaction tx); diff --git a/src/Voron/Impl/FreeSpace/NoFreeSpaceHandling.cs b/src/Voron/Impl/FreeSpace/NoFreeSpaceHandling.cs index 0564f9b31ec2..dd27d0078760 100644 --- a/src/Voron/Impl/FreeSpace/NoFreeSpaceHandling.cs +++ b/src/Voron/Impl/FreeSpace/NoFreeSpaceHandling.cs @@ -14,6 +14,11 @@ public List AllPages(LowLevelTransaction tx) return new List(); } + public int GetFreePagesCount(LowLevelTransaction txLowLevelTransaction) + { + return 0; + } + public void FreePage(LowLevelTransaction tx, long pageNumber) { diff --git a/src/Voron/Impl/FreeSpace/StreamBitArray.cs b/src/Voron/Impl/FreeSpace/StreamBitArray.cs index 258bdb983dec..da10ba61a95c 100644 --- a/src/Voron/Impl/FreeSpace/StreamBitArray.cs +++ b/src/Voron/Impl/FreeSpace/StreamBitArray.cs @@ -35,6 +35,7 @@ using System; using System.Diagnostics; using System.IO; +using System.Numerics; using Sparrow.Server; namespace Voron.Impl.FreeSpace @@ -110,6 +111,18 @@ public bool Get(int index) return (_inner[index >> 5] & (1 << (index & 31))) != 0; } + public int GetNumberOfSetBits() + { + var count = 0; + + for (int i = 0; i < _inner.Length; i++) + { + count += BitOperations.PopCount((uint)_inner[i]); + } + + return count; + } + public void Set(int index, bool value) { if (value)