Merge pull request #145 from RamType-0/TaskPoolNodeBenchmark

Add TaskPoolRefNode benchmark
pull/149/head
Yoshifumi Kawai 2020-08-28 11:15:57 +09:00 committed by GitHub
commit a65f4da7a2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 77 additions and 0 deletions

View File

@ -10,11 +10,14 @@ public class QueueCheck
{ {
Node node1 = new Node(); Node node1 = new Node();
Node node2 = new Node(); Node node2 = new Node();
RefNode refNode1 = new RefNode();
RefNode refNode2 = new RefNode();
Queue<Node> q1 = new Queue<Node>(); Queue<Node> q1 = new Queue<Node>();
Stack<Node> s1 = new Stack<Node>(); Stack<Node> s1 = new Stack<Node>();
ConcurrentQueue<Node> cq = new ConcurrentQueue<Node>(); ConcurrentQueue<Node> cq = new ConcurrentQueue<Node>();
ConcurrentStack<Node> cs = new ConcurrentStack<Node>(); ConcurrentStack<Node> cs = new ConcurrentStack<Node>();
static TaskPool<Node> pool; static TaskPool<Node> pool;
static TaskPoolRefNode<RefNode> poolRefNode;
static TaskPoolEqualNull<Node> poolEqualNull; static TaskPoolEqualNull<Node> poolEqualNull;
static TaskPoolClass<Node> poolClass = new TaskPoolClass<Node>(); static TaskPoolClass<Node> poolClass = new TaskPoolClass<Node>();
static TaskPoolWithoutSize<Node> poolWithoutSize; static TaskPoolWithoutSize<Node> poolWithoutSize;
@ -82,6 +85,14 @@ public class QueueCheck
pool.TryPop(out _); pool.TryPop(out _);
pool.TryPop(out _); pool.TryPop(out _);
} }
[Benchmark]
public void TaskPoolRefNode()
{
poolRefNode.TryPush(refNode1);
poolRefNode.TryPush(refNode2);
poolRefNode.TryPop(out _);
poolRefNode.TryPop(out _);
}
[Benchmark] [Benchmark]
public void TaskPoolEqualNull() public void TaskPoolEqualNull()
@ -130,6 +141,18 @@ public interface ITaskPoolNode<T>
T NextNode { get; set; } T NextNode { get; set; }
} }
public sealed class RefNode :ITaskPoolRefNode<RefNode>
{
RefNode nextNode;
public ref RefNode NextNode => ref nextNode;
}
public interface ITaskPoolRefNode<T>
{
ref T NextNode { get; }
}
// mutable struct, don't mark readonly. // mutable struct, don't mark readonly.
[StructLayout(LayoutKind.Auto)] [StructLayout(LayoutKind.Auto)]
public struct TaskPoolWithoutLock<T> public struct TaskPoolWithoutLock<T>
@ -237,6 +260,60 @@ public struct TaskPool<T>
return false; return false;
} }
} }
[StructLayout(LayoutKind.Auto)]
public struct TaskPoolRefNode<T>
where T : class, ITaskPoolRefNode<T>
{
int gate;
int size;
T root;
public int Size => size;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool TryPop(out T result)
{
if (Interlocked.CompareExchange(ref gate, 1, 0) == 0)
{
var v = root;
if (!(v is null))
{
ref var nextNode = ref v.NextNode;
root = nextNode;
nextNode = null;
size--;
result = v;
Volatile.Write(ref gate, 0);
return true;
}
Volatile.Write(ref gate, 0);
}
result = default;
return false;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool TryPush(T item)
{
if (Interlocked.CompareExchange(ref gate, 1, 0) == 0)
{
//if (size < TaskPool.MaxPoolSize)
{
item.NextNode = root;
root = item;
size++;
Volatile.Write(ref gate, 0);
return true;
}
//else
{
// Volatile.Write(ref gate, 0);
}
}
return false;
}
}
[StructLayout(LayoutKind.Auto)] [StructLayout(LayoutKind.Auto)]
public struct TaskPoolEqualNull<T> public struct TaskPoolEqualNull<T>