Browse Source

Merge pull request #61 from Akeit0/optimize-coroutine

Optimize: Reduce unnecessary coping in coroutine
Annulus Games 11 months ago
parent
commit
f633588a0c
2 changed files with 16 additions and 24 deletions
  1. 1 0
      sandbox/Benchmark/CoroutineBenchmark.cs
  2. 15 24
      src/Lua/LuaCoroutine.cs

+ 1 - 0
sandbox/Benchmark/CoroutineBenchmark.cs

@@ -14,6 +14,7 @@ public class CoroutineBenchmark
     {
         core.Setup("coroutine.lua");
         core.LuaCSharpState.OpenBasicLibrary();
+        core.LuaCSharpState.OpenCoroutineLibrary();
     }
 
     [Benchmark(Description = "MoonSharp (RunString)")]

+ 15 - 24
src/Lua/LuaCoroutine.cs

@@ -60,9 +60,10 @@ public sealed class LuaCoroutine : LuaThread, IValueTaskSource<LuaCoroutine.Yiel
                     if (isFirstCall)
                     {
                         // copy stack value
-                        Stack.EnsureCapacity(baseThread.Stack.Count);
-                        baseThread.Stack.AsSpan().CopyTo(Stack.GetBuffer());
-                        Stack.NotifyTop(baseThread.Stack.Count);
+                        var argCount = context.ArgumentCount;
+                        Stack.EnsureCapacity(argCount);
+                        baseThread.Stack.AsSpan()[^argCount..].CopyTo(Stack.GetBuffer());
+                        Stack.NotifyTop(argCount);
                     }
                     else
                     {
@@ -122,27 +123,19 @@ public sealed class LuaCoroutine : LuaThread, IValueTaskSource<LuaCoroutine.Yiel
                     if (variableArgumentCount > 0)
                     {
                         var fixedArgumentCount = context.ArgumentCount - 1 - variableArgumentCount;
+                        var args = context.Arguments;
 
-                        for (int i = 0; i < variableArgumentCount; i++)
-                        {
-                            Stack.Push(context.GetArgument(i + fixedArgumentCount + 1));
-                        }
+                        Stack.PushRange(args.Slice(1 + fixedArgumentCount, variableArgumentCount));
 
                         frameBase = Stack.Count;
 
-                        for (int i = 0; i < fixedArgumentCount; i++)
-                        {
-                            Stack.Push(context.GetArgument(i + 1));
-                        }
+                        Stack.PushRange(args.Slice(1, fixedArgumentCount));
                     }
                     else
                     {
                         frameBase = Stack.Count;
 
-                        for (int i = 0; i < context.ArgumentCount - 1; i++)
-                        {
-                            Stack.Push(context.GetArgument(i + 1));
-                        }
+                        Stack.PushRange(context.Arguments[1..]);
                     }
 
                     functionTask = Function.InvokeAsync(new()
@@ -156,17 +149,15 @@ public sealed class LuaCoroutine : LuaThread, IValueTaskSource<LuaCoroutine.Yiel
                     Volatile.Write(ref isFirstCall, false);
                 }
 
-                (var index, var result0, var result1) = await ValueTaskEx.WhenAny(resumeTask, functionTask!);
+                var (index, result0, result1) = await ValueTaskEx.WhenAny(resumeTask, functionTask!);
 
+                var bufferSpan = buffer.Span;
                 if (index == 0)
                 {
                     var results = result0.Results;
 
-                    buffer.Span[0] = true;
-                    for (int i = 0; i < results.Length; i++)
-                    {
-                        buffer.Span[i + 1] = results[i];
-                    }
+                    bufferSpan[0] = true;
+                    results.CopyTo(bufferSpan[1..]);
 
                     return results.Length + 1;
                 }
@@ -175,8 +166,8 @@ public sealed class LuaCoroutine : LuaThread, IValueTaskSource<LuaCoroutine.Yiel
                     var resultCount = functionTask!.Result;
 
                     Volatile.Write(ref status, (byte)LuaThreadStatus.Dead);
-                    buffer.Span[0] = true;
-                    this.buffer[0..resultCount].CopyTo(buffer.Span[1..]);
+                    bufferSpan[0] = true;
+                    this.buffer.AsSpan()[..resultCount].CopyTo(bufferSpan[1..]);
 
                     ArrayPool<LuaValue>.Shared.Return(this.buffer);
 
@@ -191,7 +182,7 @@ public sealed class LuaCoroutine : LuaThread, IValueTaskSource<LuaCoroutine.Yiel
 
                     Volatile.Write(ref status, (byte)LuaThreadStatus.Dead);
                     buffer.Span[0] = false;
-                    buffer.Span[1] = ex is LuaRuntimeException { ErrorObject: not null } luaEx ? luaEx.ErrorObject.Value: ex.Message;
+                    buffer.Span[1] = ex is LuaRuntimeException { ErrorObject: not null } luaEx ? luaEx.ErrorObject.Value : ex.Message;
                     return 2;
                 }
                 else