Improve AsyncTrigger performance
parent
ebe3065c34
commit
6be955816b
|
@ -212,11 +212,16 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
// optimize: many cases, handler is single.
|
// optimize: many cases, handler is single.
|
||||||
AsyncTriggerHandler<T> singleHandler;
|
AsyncTriggerHandler<T> singleHandler;
|
||||||
|
|
||||||
List<AsyncTriggerHandler<T>> handlers;
|
AsyncTriggerHandler<T>[] handlers;
|
||||||
|
|
||||||
|
// when running(in TrySetResult), does not add immediately.
|
||||||
|
bool isRunning;
|
||||||
|
AsyncTriggerHandler<T> waitHandler;
|
||||||
|
MinimumQueue<AsyncTriggerHandler<T>> waitQueue;
|
||||||
|
|
||||||
public bool TrySetResult(T value)
|
public bool TrySetResult(T value)
|
||||||
{
|
{
|
||||||
List<Exception> exceptions = null;
|
isRunning = true;
|
||||||
|
|
||||||
if (singleHandler != null)
|
if (singleHandler != null)
|
||||||
{
|
{
|
||||||
|
@ -226,56 +231,44 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
if (handlers == null)
|
Debug.LogException(ex);
|
||||||
{
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
exceptions = new List<Exception>();
|
|
||||||
exceptions.Add(ex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handlers != null)
|
if (handlers != null)
|
||||||
{
|
{
|
||||||
// make snapshot
|
for (int i = 0; i < handlers.Length; i++)
|
||||||
var rentArray = ArrayPoolUtil.CopyToRentArray(handlers);
|
|
||||||
var clearArray = true;
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
var array = rentArray.Array;
|
if (handlers[i] != null)
|
||||||
var len = rentArray.Length;
|
|
||||||
for (int i = 0; i < len; i++)
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
((IResolvePromise<T>)array[i]).TrySetResult(value);
|
((IResolvePromise<T>)handlers[i]).TrySetResult(value);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
if (exceptions == null)
|
handlers[i] = null;
|
||||||
{
|
Debug.LogException(ex);
|
||||||
exceptions = new List<Exception>();
|
|
||||||
}
|
|
||||||
exceptions.Add(ex);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
array[i] = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally
|
|
||||||
{
|
|
||||||
rentArray.DisposeManually(clearArray);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exceptions != null)
|
isRunning = false;
|
||||||
|
|
||||||
|
if (waitHandler != null)
|
||||||
{
|
{
|
||||||
throw new AggregateException(exceptions);
|
var h = waitHandler;
|
||||||
|
waitHandler = null;
|
||||||
|
Add(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (waitQueue != null)
|
||||||
|
{
|
||||||
|
while (waitQueue.Count != 0)
|
||||||
|
{
|
||||||
|
Add(waitQueue.Dequeue());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -283,7 +276,7 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
|
|
||||||
public bool TrySetCanceled(CancellationToken cancellationToken)
|
public bool TrySetCanceled(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
List<Exception> exceptions = null;
|
isRunning = true;
|
||||||
|
|
||||||
if (singleHandler != null)
|
if (singleHandler != null)
|
||||||
{
|
{
|
||||||
|
@ -293,56 +286,44 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
if (handlers == null)
|
Debug.LogException(ex);
|
||||||
{
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
exceptions = new List<Exception>();
|
|
||||||
exceptions.Add(ex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handlers != null)
|
if (handlers != null)
|
||||||
{
|
{
|
||||||
// make snapshot
|
for (int i = 0; i < handlers.Length; i++)
|
||||||
var rentArray = ArrayPoolUtil.CopyToRentArray(handlers);
|
|
||||||
var clearArray = true;
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
var array = rentArray.Array;
|
if (handlers[i] != null)
|
||||||
var len = rentArray.Length;
|
|
||||||
for (int i = 0; i < len; i++)
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
((ICancelPromise)array[i]).TrySetCanceled(cancellationToken);
|
((ICancelPromise)handlers[i]).TrySetCanceled(cancellationToken);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
if (exceptions == null)
|
Debug.LogException(ex);
|
||||||
{
|
handlers[i] = null;
|
||||||
exceptions = new List<Exception>();
|
|
||||||
}
|
|
||||||
exceptions.Add(ex);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
array[i] = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally
|
|
||||||
{
|
|
||||||
rentArray.DisposeManually(clearArray);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exceptions != null)
|
isRunning = false;
|
||||||
|
|
||||||
|
if (waitHandler != null)
|
||||||
{
|
{
|
||||||
throw new AggregateException(exceptions);
|
var h = waitHandler;
|
||||||
|
waitHandler = null;
|
||||||
|
Add(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (waitQueue != null)
|
||||||
|
{
|
||||||
|
while (waitQueue.Count != 0)
|
||||||
|
{
|
||||||
|
Add(waitQueue.Dequeue());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -350,6 +331,22 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
|
|
||||||
public void Add(AsyncTriggerHandler<T> handler)
|
public void Add(AsyncTriggerHandler<T> handler)
|
||||||
{
|
{
|
||||||
|
if (isRunning)
|
||||||
|
{
|
||||||
|
if (waitHandler == null)
|
||||||
|
{
|
||||||
|
waitHandler = handler;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (waitQueue == null)
|
||||||
|
{
|
||||||
|
waitQueue = new MinimumQueue<AsyncTriggerHandler<T>>(4);
|
||||||
|
}
|
||||||
|
waitQueue.Enqueue(handler);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (singleHandler == null)
|
if (singleHandler == null)
|
||||||
{
|
{
|
||||||
singleHandler = handler;
|
singleHandler = handler;
|
||||||
|
@ -358,12 +355,36 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
{
|
{
|
||||||
if (handlers == null)
|
if (handlers == null)
|
||||||
{
|
{
|
||||||
handlers = new List<AsyncTriggerHandler<T>>();
|
handlers = new AsyncTriggerHandler<T>[4];
|
||||||
}
|
}
|
||||||
handlers.Add(handler);
|
|
||||||
|
// check empty
|
||||||
|
for (int i = 0; i < handlers.Length; i++)
|
||||||
|
{
|
||||||
|
if (handlers[i] == null)
|
||||||
|
{
|
||||||
|
handlers[i] = handler;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// full, ensure capacity
|
||||||
|
var last = handlers.Length;
|
||||||
|
{
|
||||||
|
EnsureCapacity(ref handlers);
|
||||||
|
handlers[last] = handler;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void EnsureCapacity(ref AsyncTriggerHandler<T>[] array)
|
||||||
|
{
|
||||||
|
var newSize = array.Length * 2;
|
||||||
|
var newArray = new AsyncTriggerHandler<T>[newSize];
|
||||||
|
Array.Copy(array, 0, newArray, 0, array.Length);
|
||||||
|
array = newArray;
|
||||||
|
}
|
||||||
|
|
||||||
public void Remove(AsyncTriggerHandler<T> handler)
|
public void Remove(AsyncTriggerHandler<T> handler)
|
||||||
{
|
{
|
||||||
if (singleHandler == handler)
|
if (singleHandler == handler)
|
||||||
|
@ -374,7 +395,15 @@ namespace Cysharp.Threading.Tasks.Triggers
|
||||||
{
|
{
|
||||||
if (handlers != null)
|
if (handlers != null)
|
||||||
{
|
{
|
||||||
handlers.Remove(handler);
|
for (int i = 0; i < handlers.Length; i++)
|
||||||
|
{
|
||||||
|
if (handlers[i] == handler)
|
||||||
|
{
|
||||||
|
// fill null.
|
||||||
|
handlers[i] = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,9 +124,11 @@ public class SandboxMain : MonoBehaviour
|
||||||
CancellationTokenSource cts = new CancellationTokenSource();
|
CancellationTokenSource cts = new CancellationTokenSource();
|
||||||
|
|
||||||
var trigger = this.GetAsyncUpdateTrigger();
|
var trigger = this.GetAsyncUpdateTrigger();
|
||||||
Go(trigger, cts.Token).Forget();
|
Go(trigger, 1, cts.Token).Forget();
|
||||||
//Go(trigger).Forget();
|
Go(trigger, 2, cts.Token).Forget();
|
||||||
//Go(trigger).Forget();
|
Go(trigger, 3, cts.Token).Forget();
|
||||||
|
Go(trigger, 4, cts.Token).Forget();
|
||||||
|
Go(trigger, 5, cts.Token).Forget();
|
||||||
|
|
||||||
|
|
||||||
Application.logMessageReceived += Application_logMessageReceived;
|
Application.logMessageReceived += Application_logMessageReceived;
|
||||||
|
@ -141,7 +143,7 @@ public class SandboxMain : MonoBehaviour
|
||||||
|
|
||||||
okButton.onClick.AddListener(() =>
|
okButton.onClick.AddListener(() =>
|
||||||
{
|
{
|
||||||
FooAsync().Forget();
|
// FooAsync().Forget();
|
||||||
});
|
});
|
||||||
|
|
||||||
cancelButton.onClick.AddListener(() =>
|
cancelButton.onClick.AddListener(() =>
|
||||||
|
@ -154,7 +156,7 @@ public class SandboxMain : MonoBehaviour
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async UniTaskVoid Go(AsyncUpdateTrigger trigger, CancellationToken ct)
|
async UniTaskVoid Go(AsyncUpdateTrigger trigger, int i, CancellationToken ct)
|
||||||
{
|
{
|
||||||
await UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate);
|
await UniTask.Yield(PlayerLoopTiming.LastPostLateUpdate);
|
||||||
UnityEngine.Debug.Log("AWAIT BEFO:" + Time.frameCount);
|
UnityEngine.Debug.Log("AWAIT BEFO:" + Time.frameCount);
|
||||||
|
@ -162,14 +164,16 @@ public class SandboxMain : MonoBehaviour
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
while (true)
|
while (!ct.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
await handler.UpdateAsync();
|
await handler.UpdateAsync();
|
||||||
|
//await handler.UpdateAsync();
|
||||||
|
Debug.Log("OK:" + i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
UnityEngine.Debug.Log("AWAIT END:" + Time.frameCount);
|
UnityEngine.Debug.Log("AWAIT END:" + Time.frameCount + ": No," + i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue