diff --git a/README.md b/README.md index a78c89cb..38b74ff4 100644 --- a/README.md +++ b/README.md @@ -690,6 +690,8 @@ foreach (var (type, size) in TaskPool.GetCacheSizeInfo()) } ``` +> In UnityEditor profiler shows allocation of compiler generated AsyncStateMachine but it only occurs in debug(development) build. C# Compiler generate AsyncStateMachine as class on Debug build and as struct on Release build. And also currently due to IL2CPP limitation, in IL2CPP build, UniTask do boxing AsyncStateMachine when needed so sometimes exists `one` allocation. + API References --- UniTask's API References is hosted at [cysharp.github.io/UniTask](https://cysharp.github.io/UniTask/api/Cysharp.Threading.Tasks.html) by [DocFX](https://dotnet.github.io/docfx/) and [Cysharp/DocfXTemplate](https://github.com/Cysharp/DocfxTemplate). diff --git a/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/AsyncUniTaskMethodBuilder.cs b/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/AsyncUniTaskMethodBuilder.cs index da800f75..1aa990d9 100644 --- a/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/AsyncUniTaskMethodBuilder.cs +++ b/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/AsyncUniTaskMethodBuilder.cs @@ -12,7 +12,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices [StructLayout(LayoutKind.Auto)] public struct AsyncUniTaskMethodBuilder { - internal IStateMachineRunnerPromise runnerPromise; + IStateMachineRunnerPromise runnerPromise; Exception ex; // 1. Static Create method. @@ -80,7 +80,7 @@ public void AwaitOnCompleted(ref TAwaiter awaiter, ref { if (runnerPromise == null) { - AsyncUniTask.SetStateMachine(ref this, ref stateMachine); + AsyncUniTask.SetStateMachine(ref stateMachine, ref runnerPromise); } awaiter.OnCompleted(runnerPromise.MoveNext); @@ -96,7 +96,7 @@ public void AwaitUnsafeOnCompleted(ref TAwaiter awaiter { if (runnerPromise == null) { - AsyncUniTask.SetStateMachine(ref this, ref stateMachine); + AsyncUniTask.SetStateMachine(ref stateMachine, ref runnerPromise); } awaiter.UnsafeOnCompleted(runnerPromise.MoveNext); @@ -138,7 +138,7 @@ private object ObjectIdForDebugger [StructLayout(LayoutKind.Auto)] public struct AsyncUniTaskMethodBuilder { - internal IStateMachineRunnerPromise runnerPromise; + IStateMachineRunnerPromise runnerPromise; Exception ex; T result; @@ -211,7 +211,7 @@ public void AwaitOnCompleted(ref TAwaiter awaiter, ref { if (runnerPromise == null) { - AsyncUniTask.SetStateMachine(ref this, ref stateMachine); + AsyncUniTask.SetStateMachine(ref stateMachine, ref runnerPromise); } awaiter.OnCompleted(runnerPromise.MoveNext); @@ -227,7 +227,7 @@ public void AwaitUnsafeOnCompleted(ref TAwaiter awaiter { if (runnerPromise == null) { - AsyncUniTask.SetStateMachine(ref this, ref stateMachine); + AsyncUniTask.SetStateMachine(ref stateMachine, ref runnerPromise); } awaiter.UnsafeOnCompleted(runnerPromise.MoveNext); diff --git a/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/AsyncUniTaskVoidMethodBuilder.cs b/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/AsyncUniTaskVoidMethodBuilder.cs index 312e599b..754dde66 100644 --- a/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/AsyncUniTaskVoidMethodBuilder.cs +++ b/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/AsyncUniTaskVoidMethodBuilder.cs @@ -12,7 +12,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices [StructLayout(LayoutKind.Auto)] public struct AsyncUniTaskVoidMethodBuilder { - internal IStateMachineRunner runner; + IStateMachineRunner runner; // 1. Static Create method. [DebuggerHidden] @@ -70,7 +70,7 @@ public void AwaitOnCompleted(ref TAwaiter awaiter, ref { if (runner == null) { - AsyncUniTaskVoid.SetStateMachine(ref this, ref stateMachine); + AsyncUniTaskVoid.SetStateMachine(ref stateMachine, ref runner); } awaiter.OnCompleted(runner.MoveNext); @@ -86,7 +86,7 @@ public void AwaitUnsafeOnCompleted(ref TAwaiter awaiter { if (runner == null) { - AsyncUniTaskVoid.SetStateMachine(ref this, ref stateMachine); + AsyncUniTaskVoid.SetStateMachine(ref stateMachine, ref runner); } awaiter.UnsafeOnCompleted(runner.MoveNext); diff --git a/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/StateMachineRunner.cs b/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/StateMachineRunner.cs index 7cbc5abb..067c048b 100644 --- a/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/StateMachineRunner.cs +++ b/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/StateMachineRunner.cs @@ -2,6 +2,7 @@ using Cysharp.Threading.Tasks.Internal; using System; +using System.Linq; using System.Diagnostics; using System.Runtime.CompilerServices; @@ -29,12 +30,26 @@ internal interface IStateMachineRunnerPromise : IUniTaskSource void SetException(Exception exception); } + internal static class StateMachineUtility + { + public static int GetState(IAsyncStateMachine stateMachine) + { + var info = stateMachine.GetType().GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance) + .First(x => x.Name.EndsWith("__state")); + return (int)info.GetValue(stateMachine); + } + } + internal sealed class AsyncUniTaskVoid : IStateMachineRunner, ITaskPoolNode>, IUniTaskSource where TStateMachine : IAsyncStateMachine { static TaskPool> pool; +#if ENABLE_IL2CPP + IAsyncStateMachine stateMachine; // unfortunatelly boxed to fix IL2CPP issue. +#else TStateMachine stateMachine; +#endif public Action MoveNext { get; } @@ -43,7 +58,7 @@ public AsyncUniTaskVoid() MoveNext = Run; } - public static void SetStateMachine(ref AsyncUniTaskVoidMethodBuilder builder, ref TStateMachine stateMachine) + public static void SetStateMachine(ref TStateMachine stateMachine, ref IStateMachineRunner runnerFieldRef) { if (!pool.TryPop(out var result)) { @@ -51,7 +66,7 @@ public static void SetStateMachine(ref AsyncUniTaskVoidMethodBuilder builder, re } TaskTracker.TrackActiveTask(result, 3); - builder.runner = result; // set runner before copied. + runnerFieldRef = result; // set runner before copied. result.stateMachine = stateMachine; // copy struct StateMachine(in release build). } @@ -102,7 +117,11 @@ internal sealed class AsyncUniTask : IStateMachineRunnerPromise, { static TaskPool> pool; +#if ENABLE_IL2CPP + IAsyncStateMachine stateMachine; // unfortunatelly boxed to fix IL2CPP issue. +#else TStateMachine stateMachine; +#endif public Action MoveNext { get; } @@ -113,7 +132,7 @@ internal sealed class AsyncUniTask : IStateMachineRunnerPromise, MoveNext = Run; } - public static void SetStateMachine(ref AsyncUniTaskMethodBuilder builder, ref TStateMachine stateMachine) + public static void SetStateMachine(ref TStateMachine stateMachine, ref IStateMachineRunnerPromise runnerPromiseFieldRef) { if (!pool.TryPop(out var result)) { @@ -121,7 +140,7 @@ public static void SetStateMachine(ref AsyncUniTaskMethodBuilder builder, ref TS } TaskTracker.TrackActiveTask(result, 3); - builder.runnerPromise = result; // set runner before copied. + runnerPromiseFieldRef = result; // set runner before copied. result.stateMachine = stateMachine; // copy struct StateMachine(in release build). } @@ -213,7 +232,11 @@ internal sealed class AsyncUniTask : IStateMachineRunnerPromis { static TaskPool> pool; +#if ENABLE_IL2CPP + IAsyncStateMachine stateMachine; // unfortunatelly boxed to fix IL2CPP issue. +#else TStateMachine stateMachine; +#endif public Action MoveNext { get; } @@ -224,7 +247,7 @@ internal sealed class AsyncUniTask : IStateMachineRunnerPromis MoveNext = Run; } - public static void SetStateMachine(ref AsyncUniTaskMethodBuilder builder, ref TStateMachine stateMachine) + public static void SetStateMachine(ref TStateMachine stateMachine, ref IStateMachineRunnerPromise runnerPromiseFieldRef) { if (!pool.TryPop(out var result)) { @@ -232,10 +255,13 @@ public static void SetStateMachine(ref AsyncUniTaskMethodBuilder builder, ref } TaskTracker.TrackActiveTask(result, 3); - builder.runnerPromise = result; // set runner before copied. + runnerPromiseFieldRef = result; // set runner before copied. result.stateMachine = stateMachine; // copy struct StateMachine(in release build). + + // UnityEngine.Debug.Log($"SetStateMachine State:" + StateMachineUtility.GetState(stateMachine)); } + public AsyncUniTask NextNode { get; set; } static AsyncUniTask() @@ -255,6 +281,7 @@ bool TryReturn() [MethodImpl(MethodImplOptions.AggressiveInlining)] void Run() { + // UnityEngine.Debug.Log($"MoveNext State:" + StateMachineUtility.GetState(stateMachine)); stateMachine.MoveNext(); } diff --git a/src/UniTask/Assets/Plugins/UniTask/Runtime/Linq/ToArray.cs b/src/UniTask/Assets/Plugins/UniTask/Runtime/Linq/ToArray.cs index 35549681..dfdff515 100644 --- a/src/UniTask/Assets/Plugins/UniTask/Runtime/Linq/ToArray.cs +++ b/src/UniTask/Assets/Plugins/UniTask/Runtime/Linq/ToArray.cs @@ -19,6 +19,8 @@ internal static class ToArray { internal static async UniTask ToArrayAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) { + // UnityEngine.Debug.Log("Called ToArray"); + var pool = ArrayPool.Shared; var array = pool.Rent(16); diff --git a/src/UniTask/Assets/Plugins/UniTask/package.json b/src/UniTask/Assets/Plugins/UniTask/package.json index 8556bae6..40a79ccb 100644 --- a/src/UniTask/Assets/Plugins/UniTask/package.json +++ b/src/UniTask/Assets/Plugins/UniTask/package.json @@ -1,7 +1,7 @@ { "name": "com.cysharp.unitask", "displayName": "UniTask", - "version": "2.0.14", + "version": "2.0.15", "unity": "2018.4", "description": "Provides an efficient async/await integration to Unity.", "keywords": [ "async/await", "async", "Task", "UniTask" ], diff --git a/src/UniTask/Assets/Scenes/SandboxMain.cs b/src/UniTask/Assets/Scenes/SandboxMain.cs index 90d7ceed..97a33cc8 100644 --- a/src/UniTask/Assets/Scenes/SandboxMain.cs +++ b/src/UniTask/Assets/Scenes/SandboxMain.cs @@ -413,6 +413,19 @@ async UniTask DelayCheck() Debug.Log("after"); } + private async UniTaskVoid ExecuteAsync() + { + Debug.Log("1"); + { + var xs = await UniTaskAsyncEnumerable.TimerFrame(1).ToArrayAsync(); + } + Debug.Log("------------------"); + { + var xs = await UniTaskAsyncEnumerable.TimerFrame(1).ToArrayAsync(); + Debug.Log("2"); + } + } + void Start() { @@ -423,7 +436,7 @@ void Start() //StartCoroutine(TestCoroutine().ToCoroutine()); - Application.logMessageReceived += Application_logMessageReceived; + // Application.logMessageReceived += Application_logMessageReceived; @@ -432,13 +445,9 @@ void Start() okButton.onClick.AddListener(UniTask.UnityAction(async () => { - { - var xs = await UniTaskAsyncEnumerable.TimerFrame(1).ToArrayAsync(); - } - Debug.Log("------------------"); - { - var xs = await UniTaskAsyncEnumerable.TimerFrame(1).ToArrayAsync(); - } + _ = ExecuteAsync(); + + await UniTask.Yield(); //await DelayCheck(); /*