RecyclableList.IndexOf performance improvements.
This commit is contained in:
1 parent
21c82d80a2
commit
db8ee72c59
2 files changed
+74
-21
No files matched your search
@@ -3,6 +3,10 @@ namespace Recyclable.Collections.Parallel
|
|||||||
public sealed class IndexOfSynchronizationContext
|
public sealed class IndexOfSynchronizationContext
|
||||||
{
|
{
|
||||||
private readonly SpinWait _participantsSpinWait = new();
|
private readonly SpinWait _participantsSpinWait = new();
|
||||||
|
private readonly SpinLock _participantsSpinLock = new(false);
|
||||||
|
private readonly SpinLock _indexOfSpinLock = new(false);
|
||||||
|
private bool _indexOfLockTaken;
|
||||||
|
|
||||||
|
|
||||||
internal bool _isItemFound;
|
internal bool _isItemFound;
|
||||||
internal int _participants;
|
internal int _participants;
|
||||||
@@ -10,12 +14,29 @@ namespace Recyclable.Collections.Parallel
|
|||||||
|
|
||||||
public void AddParticipant()
|
public void AddParticipant()
|
||||||
{
|
{
|
||||||
_ = Interlocked.Increment(ref _participants);
|
bool lockTaken = false;
|
||||||
|
_participantsSpinLock.Enter(ref lockTaken);
|
||||||
|
_participants++;
|
||||||
|
if (lockTaken)
|
||||||
|
{
|
||||||
|
_participantsSpinLock.Exit(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddParticipants(int newParticipants)
|
public void AddParticipants(int newParticipants)
|
||||||
{
|
{
|
||||||
_ = Interlocked.Add(ref _participants, newParticipants);
|
bool lockTaken = false;
|
||||||
|
_participantsSpinLock.Enter(ref lockTaken);
|
||||||
|
_participants += newParticipants;
|
||||||
|
if (lockTaken)
|
||||||
|
{
|
||||||
|
_participantsSpinLock.Exit(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Lock()
|
||||||
|
{
|
||||||
|
_indexOfSpinLock.Enter(ref _indexOfLockTaken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveParticipants(int participantsToRemove)
|
public void RemoveParticipants(int participantsToRemove)
|
||||||
@@ -25,7 +46,13 @@ namespace Recyclable.Collections.Parallel
|
|||||||
ThrowNotEnoughParticipants();
|
ThrowNotEnoughParticipants();
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = Interlocked.Add(ref _participants, -participantsToRemove);
|
bool lockTaken = false;
|
||||||
|
_participantsSpinLock.Enter(ref lockTaken);
|
||||||
|
_participants -= participantsToRemove;
|
||||||
|
if (lockTaken)
|
||||||
|
{
|
||||||
|
_participantsSpinLock.Exit(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveParticipant()
|
public void RemoveParticipant()
|
||||||
@@ -35,7 +62,13 @@ namespace Recyclable.Collections.Parallel
|
|||||||
ThrowNoMoreParticipants();
|
ThrowNoMoreParticipants();
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = Interlocked.Decrement(ref _participants);
|
bool lockTaken = false;
|
||||||
|
_participantsSpinLock.Enter(ref lockTaken);
|
||||||
|
_participants--;
|
||||||
|
if (lockTaken)
|
||||||
|
{
|
||||||
|
_participantsSpinLock.Exit(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SignalAndWait()
|
public void SignalAndWait()
|
||||||
@@ -45,13 +78,28 @@ namespace Recyclable.Collections.Parallel
|
|||||||
ThrowNoMoreParticipants();
|
ThrowNoMoreParticipants();
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = Interlocked.Decrement(ref _participants);
|
bool lockTaken = false;
|
||||||
|
_participantsSpinLock.Enter(ref lockTaken);
|
||||||
|
_participants--;
|
||||||
|
if (lockTaken)
|
||||||
|
{
|
||||||
|
_participantsSpinLock.Exit(false);
|
||||||
|
}
|
||||||
|
|
||||||
while (_participants > 0)
|
while (_participants > 0)
|
||||||
{
|
{
|
||||||
_participantsSpinWait.SpinOnce();
|
_participantsSpinWait.SpinOnce();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Unlock()
|
||||||
|
{
|
||||||
|
if (_indexOfLockTaken)
|
||||||
|
{
|
||||||
|
_indexOfSpinLock.Exit(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void ThrowNotEnoughParticipants() => throw new InvalidOperationException("Participant cannot be removed, because there are not enough participants.");
|
private static void ThrowNotEnoughParticipants() => throw new InvalidOperationException("Participant cannot be removed, because there are not enough participants.");
|
||||||
private static void ThrowNoMoreParticipants() => throw new InvalidOperationException("Participant cannot be removed, because there are no more participants.");
|
private static void ThrowNoMoreParticipants() => throw new InvalidOperationException("Participant cannot be removed, because there are no more participants.");
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,9 @@ namespace Recyclable.Collections
|
|||||||
else if (index >= 0)
|
else if (index >= 0)
|
||||||
{
|
{
|
||||||
context._isItemFound = true;
|
context._isItemFound = true;
|
||||||
_ = Interlocked.Exchange(ref context.FoundItemIndex, (blockIndex << list._blockSizePow2BitShift) + index);
|
context.Lock();
|
||||||
|
context.FoundItemIndex = ((long)blockIndex << list._blockSizePow2BitShift) + index;
|
||||||
|
context.Unlock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,7 +39,9 @@ namespace Recyclable.Collections
|
|||||||
else if (index >= 0)
|
else if (index >= 0)
|
||||||
{
|
{
|
||||||
context._isItemFound = true;
|
context._isItemFound = true;
|
||||||
_ = Interlocked.Exchange(ref context.FoundItemIndex, ((blockIndex + 1) << list._blockSizePow2BitShift) + index);
|
context.Lock();
|
||||||
|
context.FoundItemIndex = ((long)(blockIndex + 1) << list._blockSizePow2BitShift) + index;
|
||||||
|
context.Unlock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,7 +53,9 @@ namespace Recyclable.Collections
|
|||||||
else if (index >= 0)
|
else if (index >= 0)
|
||||||
{
|
{
|
||||||
context._isItemFound = true;
|
context._isItemFound = true;
|
||||||
_ = Interlocked.Exchange(ref context.FoundItemIndex, ((blockIndex + 2) << list._blockSizePow2BitShift) + index);
|
context.Lock();
|
||||||
|
context.FoundItemIndex = ((long)(blockIndex + 2) << list._blockSizePow2BitShift) + index;
|
||||||
|
context.Unlock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,7 +63,9 @@ namespace Recyclable.Collections
|
|||||||
if (!context._isItemFound && index >= 0)
|
if (!context._isItemFound && index >= 0)
|
||||||
{
|
{
|
||||||
context._isItemFound = true;
|
context._isItemFound = true;
|
||||||
_ = Interlocked.Exchange(ref context.FoundItemIndex, ((blockIndex + 3) << list._blockSizePow2BitShift) + index);
|
context.Lock();
|
||||||
|
context.FoundItemIndex = ((long)(blockIndex + 3) << list._blockSizePow2BitShift) + index;
|
||||||
|
context.Unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@@ -87,7 +95,9 @@ namespace Recyclable.Collections
|
|||||||
if (!context._isItemFound && index >= 0)
|
if (!context._isItemFound && index >= 0)
|
||||||
{
|
{
|
||||||
context._isItemFound = true;
|
context._isItemFound = true;
|
||||||
_ = Interlocked.Exchange(ref context.FoundItemIndex, (blockIndex << list._blockSizePow2BitShift) + index);
|
context.Lock();
|
||||||
|
context.FoundItemIndex = ((long)blockIndex << list._blockSizePow2BitShift) + index;
|
||||||
|
context.Unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@@ -176,7 +186,9 @@ namespace Recyclable.Collections
|
|||||||
if (!context._isItemFound && itemIndex >= 0)
|
if (!context._isItemFound && itemIndex >= 0)
|
||||||
{
|
{
|
||||||
context._isItemFound = true;
|
context._isItemFound = true;
|
||||||
_ = Interlocked.Exchange(ref context.FoundItemIndex, ((long)blockIndex << list._blockSizePow2BitShift) + itemIndex);
|
context.Lock();
|
||||||
|
context.FoundItemIndex = ((long)blockIndex << list._blockSizePow2BitShift) + itemIndex;
|
||||||
|
context.Unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,16 +261,9 @@ namespace Recyclable.Collections
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (blockIndex == list._lastBlockWithData)
|
itemIndex = list._nextItemIndex != 0
|
||||||
//{
|
? Array.IndexOf(memoryBlocksSpan[list._lastBlockWithData], item, 0, list._nextItemIndex)
|
||||||
itemIndex = list._nextItemIndex != 0
|
: Array.IndexOf(memoryBlocksSpan[list._lastBlockWithData], item, 0, list._blockSize);
|
||||||
? Array.IndexOf(memoryBlocksSpan[list._lastBlockWithData], item, 0, list._nextItemIndex)
|
|
||||||
: Array.IndexOf(memoryBlocksSpan[list._lastBlockWithData], item, 0, list._blockSize);
|
|
||||||
//}
|
|
||||||
//else
|
|
||||||
//{
|
|
||||||
// return RecyclableDefaults.ItemNotFoundIndexLong;
|
|
||||||
//}
|
|
||||||
|
|
||||||
return itemIndex >= 0 ? itemIndex + ((long)list._lastBlockWithData << list._blockSizePow2BitShift) : RecyclableDefaults.ItemNotFoundIndexLong;
|
return itemIndex >= 0 ? itemIndex + ((long)list._lastBlockWithData << list._blockSizePow2BitShift) : RecyclableDefaults.ItemNotFoundIndexLong;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user