From 0bdc933c2097cad1505871852278b367ad8e5e6b Mon Sep 17 00:00:00 2001 From: "Ram.Type-0" Date: Fri, 28 Aug 2020 10:54:33 +0900 Subject: [PATCH] Add TaskPoolRefNode benchmark --- src/UniTask.NetCoreSandbox/QueueCheck.cs | 77 ++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/src/UniTask.NetCoreSandbox/QueueCheck.cs b/src/UniTask.NetCoreSandbox/QueueCheck.cs index db55939..3e0937c 100644 --- a/src/UniTask.NetCoreSandbox/QueueCheck.cs +++ b/src/UniTask.NetCoreSandbox/QueueCheck.cs @@ -10,11 +10,14 @@ public class QueueCheck { Node node1 = new Node(); Node node2 = new Node(); + RefNode refNode1 = new RefNode(); + RefNode refNode2 = new RefNode(); Queue q1 = new Queue(); Stack s1 = new Stack(); ConcurrentQueue cq = new ConcurrentQueue(); ConcurrentStack cs = new ConcurrentStack(); static TaskPool pool; + static TaskPoolRefNode poolRefNode; static TaskPoolEqualNull poolEqualNull; static TaskPoolClass poolClass = new TaskPoolClass(); static TaskPoolWithoutSize poolWithoutSize; @@ -82,6 +85,14 @@ public class QueueCheck pool.TryPop(out _); pool.TryPop(out _); } + [Benchmark] + public void TaskPoolRefNode() + { + poolRefNode.TryPush(refNode1); + poolRefNode.TryPush(refNode2); + poolRefNode.TryPop(out _); + poolRefNode.TryPop(out _); + } [Benchmark] public void TaskPoolEqualNull() @@ -130,6 +141,18 @@ public interface ITaskPoolNode T NextNode { get; set; } } +public sealed class RefNode :ITaskPoolRefNode +{ + RefNode nextNode; + public ref RefNode NextNode => ref nextNode; +} + +public interface ITaskPoolRefNode +{ + ref T NextNode { get; } +} + + // mutable struct, don't mark readonly. [StructLayout(LayoutKind.Auto)] public struct TaskPoolWithoutLock @@ -237,6 +260,60 @@ public struct TaskPool return false; } } +[StructLayout(LayoutKind.Auto)] +public struct TaskPoolRefNode + where T : class, ITaskPoolRefNode +{ + 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)] public struct TaskPoolEqualNull