public void Coalescing() { var allocator = new HeapAllocator(100); allocator.DebugValidateInternalState(); // Try to allocate ten blocks. These should succeed, because the heap should not be fragmented yet. var blocks10 = Enumerable.Range(0, 10).Select(x => allocator.Allocate(10)).ToArray(); allocator.DebugValidateInternalState(); Assert.IsTrue(blocks10.All(b => b.Length == 10)); Assert.IsTrue(allocator.Full); // Release all of them. foreach (var b in blocks10) { allocator.Release(b); allocator.DebugValidateInternalState(); } // Now try to allocate the entire heap. It should succeed, because everything has been freed. Assert.AreEqual(allocator.Allocate(100).Length, 100); allocator.DebugValidateInternalState(); allocator.Dispose(); }
public void BasicTests() { var allocator = new HeapAllocator(1000); allocator.DebugValidateInternalState(); Assert.AreEqual(allocator.FreeSpace, 1000); HeapBlock b10 = allocator.Allocate(10); allocator.DebugValidateInternalState(); HeapBlock b100 = allocator.Allocate(100); allocator.DebugValidateInternalState(); // Check that the allocations have sufficient size. Assert.GreaterOrEqual(b10.Length, 10); Assert.GreaterOrEqual(b100.Length, 100); // Check that the amount of free space has decreased accordingly. Assert.LessOrEqual(allocator.FreeSpace, 1000 - 100 - 10); allocator.Release(b10); allocator.DebugValidateInternalState(); allocator.Release(b100); allocator.DebugValidateInternalState(); // Everything should now be freed. Assert.AreEqual(allocator.FreeSpace, 1000); allocator.Dispose(); }
public void RandomStressTest() { const int HeapSize = 1_000_000; const int NumBlocks = 1_000; const int NumRounds = 20; const int MaxAlloc = 10_000; const int OperationsPerRound = 4_000; int numAllocs = 0; int numReleases = 0; int numFailed = 0; var rnd = new System.Random(293875); var allocator = new HeapAllocator(HeapSize); var blocks = Enumerable.Range(0, NumBlocks).Select(x => new HeapBlock()).ToArray(); var blockEnds = new SortedSet <ulong>(); // Stress test the allocator by doing a bunch of random allocs and deallocs and // try to verify that allocator internal asserts don't fire, and free space behaves // as expected. for (int i = 0; i < NumRounds; ++i) { Assert.IsTrue(allocator.Empty); // Perform random alloc/dealloc operations for (int j = 0; j < OperationsPerRound; ++j) { ulong before = allocator.FreeSpace; int b = rnd.Next(NumBlocks); int size = 0; if (blocks[b].Empty) { size = rnd.Next(1, MaxAlloc); blocks[b] = allocator.Allocate((ulong)size); allocator.DebugValidateInternalState(); if (blocks[b].Empty) { size = 0; ++numFailed; } else { size = (int)blocks[b].Length; bool added = blockEnds.Add(blocks[b].end); Assert.IsTrue(added); } ++numAllocs; } else { size = -(int)blocks[b].Length; allocator.Release(blocks[b]); allocator.DebugValidateInternalState(); bool removed = blockEnds.Remove(blocks[b].end); Assert.IsTrue(removed); blocks[b] = new HeapBlock(); ++numReleases; } ulong after = allocator.FreeSpace; ulong highest = allocator.OnePastHighestUsedAddress; Assert.AreEqual((long)after, (long)before - size); if (blockEnds.Count > 0) { Assert.AreEqual(blockEnds.Max, highest); } else { Assert.AreEqual(0, highest); } } for (int b = 0; b < NumBlocks; ++b) { if (!blocks[b].Empty) { allocator.Release(blocks[b]); blocks[b] = new HeapBlock(); blockEnds.Clear(); } } Assert.IsTrue(allocator.Empty); } Debug.Log($"Allocs: {numAllocs}, Releases: {numReleases}, Failed: {numFailed}"); allocator.Dispose(); }