Use pooled arrays in RecyclableDictionary
This commit is contained in:
1 parent
0f2d05f60d
commit
f9af1086e5
1 file changed
+66
-7
@@ -2,6 +2,7 @@ using System.Collections;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
using Recyclable.Collections.Pools;
|
||||||
|
|
||||||
namespace Recyclable.Collections
|
namespace Recyclable.Collections
|
||||||
{
|
{
|
||||||
@@ -14,7 +15,9 @@ namespace Recyclable.Collections
|
|||||||
private readonly int _blockSizeMinus1;
|
private readonly int _blockSizeMinus1;
|
||||||
private readonly byte _blockShift;
|
private readonly byte _blockShift;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
private Entry[][] _entries;
|
private Entry[][] _entries;
|
||||||
|
#nullable restore
|
||||||
private int[] _buckets;
|
private int[] _buckets;
|
||||||
private int _count;
|
private int _count;
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
@@ -38,8 +41,12 @@ namespace Recyclable.Collections
|
|||||||
_blockSizeMinus1 = blockSize - 1;
|
_blockSizeMinus1 = blockSize - 1;
|
||||||
_blockShift = (byte)(31 - BitOperations.LeadingZeroCount((uint)blockSize));
|
_blockShift = (byte)(31 - BitOperations.LeadingZeroCount((uint)blockSize));
|
||||||
|
|
||||||
_entries = new Entry[4][];
|
_entries = 4 >= RecyclableDefaults.MinPooledArrayLength
|
||||||
_entries[0] = new Entry[blockSize];
|
? RecyclableArrayPool<Entry[]>.RentShared(4)
|
||||||
|
: new Entry[4][];
|
||||||
|
_entries[0] = blockSize >= RecyclableDefaults.MinPooledArrayLength
|
||||||
|
? RecyclableArrayPool<Entry>.RentShared(blockSize)
|
||||||
|
: new Entry[blockSize];
|
||||||
_buckets = new int[4];
|
_buckets = new int[4];
|
||||||
Array.Fill(_buckets, -1);
|
Array.Fill(_buckets, -1);
|
||||||
}
|
}
|
||||||
@@ -171,11 +178,37 @@ namespace Recyclable.Collections
|
|||||||
|
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
if (_needsClearing)
|
if (_count == 0)
|
||||||
{
|
{
|
||||||
for (var i = 0; i < _count; i++)
|
Array.Fill(_buckets, -1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int blockIndex = 0;
|
||||||
|
if (_blockSize >= RecyclableDefaults.MinPooledArrayLength)
|
||||||
|
{
|
||||||
|
while (blockIndex < _entries.Length && _entries[blockIndex] != null)
|
||||||
{
|
{
|
||||||
ClearEntry(i);
|
RecyclableArrayPool<Entry>.ReturnShared(_entries[blockIndex]!, _needsClearing);
|
||||||
|
_entries[blockIndex++] = null!;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_needsClearing)
|
||||||
|
{
|
||||||
|
while (blockIndex < _entries.Length && _entries[blockIndex] != null)
|
||||||
|
{
|
||||||
|
Array.Clear(_entries[blockIndex]!, 0, _entries[blockIndex]!.Length);
|
||||||
|
_entries[blockIndex++] = null!;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (blockIndex < _entries.Length && _entries[blockIndex] != null)
|
||||||
|
{
|
||||||
|
_entries[blockIndex++] = null!;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,6 +234,16 @@ namespace Recyclable.Collections
|
|||||||
}
|
}
|
||||||
|
|
||||||
Clear();
|
Clear();
|
||||||
|
if (_entries.Length >= RecyclableDefaults.MinPooledArrayLength)
|
||||||
|
{
|
||||||
|
RecyclableArrayPool<Entry[]>.ReturnShared(_entries, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_buckets.Length >= RecyclableDefaults.MinPooledArrayLength)
|
||||||
|
{
|
||||||
|
RecyclableArrayPool<int>.ReturnShared(_buckets, false);
|
||||||
|
}
|
||||||
|
|
||||||
_entries = Array.Empty<Entry[]>();
|
_entries = Array.Empty<Entry[]>();
|
||||||
_buckets = Array.Empty<int>();
|
_buckets = Array.Empty<int>();
|
||||||
_disposed = true;
|
_disposed = true;
|
||||||
@@ -254,12 +297,28 @@ namespace Recyclable.Collections
|
|||||||
int requiredBlocks = (min + _blockSizeMinus1) >> _blockShift;
|
int requiredBlocks = (min + _blockSizeMinus1) >> _blockShift;
|
||||||
if (_entries.Length < requiredBlocks)
|
if (_entries.Length < requiredBlocks)
|
||||||
{
|
{
|
||||||
Array.Resize(ref _entries, requiredBlocks);
|
var newBlocks = requiredBlocks >= RecyclableDefaults.MinPooledArrayLength
|
||||||
|
? RecyclableArrayPool<Entry[]>.RentShared(requiredBlocks)
|
||||||
|
: new Entry[requiredBlocks][];
|
||||||
|
|
||||||
|
Array.Copy(_entries, newBlocks, _entries.Length);
|
||||||
|
|
||||||
|
if (_entries.Length >= RecyclableDefaults.MinPooledArrayLength)
|
||||||
|
{
|
||||||
|
RecyclableArrayPool<Entry[]>.ReturnShared(_entries, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
_entries = newBlocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < requiredBlocks; i++)
|
for (int i = 0; i < requiredBlocks; i++)
|
||||||
{
|
{
|
||||||
_entries[i] ??= new Entry[_blockSize];
|
if (_entries[i] == null)
|
||||||
|
{
|
||||||
|
_entries[i] = _blockSize >= RecyclableDefaults.MinPooledArrayLength
|
||||||
|
? RecyclableArrayPool<Entry>.RentShared(_blockSize)
|
||||||
|
: new Entry[_blockSize];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user