Explorar o código

Improve hook check performance

Akeit0 hai 7 meses
pai
achega
d3e99c43fd

+ 40 - 0
sandbox/Benchmark/HookedBenchmark.cs

@@ -0,0 +1,40 @@
+using BenchmarkDotNet.Attributes;
+using Lua;
+using Lua.Standard;
+
+[Config(typeof(BenchmarkConfig))]
+public class HookedBenchmark
+{
+    BenchmarkCore core = default!;
+    LuaValue[] buffer = new LuaValue[1];
+
+    [IterationSetup]
+    public void Setup()
+    {
+        core = new();
+        core.Setup("hooked.lua");
+        core.LuaCSharpState.OpenStandardLibraries();
+    }
+
+    [IterationCleanup]
+    public void Cleanup()
+    {
+        core.Dispose();
+        core = default!;
+        GC.Collect();
+    }
+
+
+    [Benchmark(Description = "NLua (DoString)", Baseline = true)]
+    public object[] Benchmark_NLua_String()
+    {
+        return core.NLuaState.DoString(core.SourceText);
+    }
+
+    [Benchmark(Description = "Lua-CSharp (DoString)")]
+    public async Task<LuaValue> Benchmark_LuaCSharp_String()
+    {
+        await core.LuaCSharpState.DoStringAsync(core.SourceText, buffer);
+        return buffer[0];
+    }
+}

+ 16 - 16
sandbox/Benchmark/NBodyBenchmark.cs

@@ -31,11 +31,11 @@ public class NBodyBenchmark
         return core.MoonSharpState.DoString(core.SourceText);
         return core.MoonSharpState.DoString(core.SourceText);
     }
     }
 
 
-    // [Benchmark(Description = "MoonSharp (RunFile)")]
-    // public DynValue Benchmark_MoonSharp_File()
-    // {
-    //     return core.MoonSharpState.DoFile(core.FilePath);
-    // }
+    [Benchmark(Description = "MoonSharp (RunFile)")]
+    public DynValue Benchmark_MoonSharp_File()
+    {
+        return core.MoonSharpState.DoFile(core.FilePath);
+    }
 
 
     [Benchmark(Description = "NLua (DoString)", Baseline = true)]
     [Benchmark(Description = "NLua (DoString)", Baseline = true)]
     public object[] Benchmark_NLua_String()
     public object[] Benchmark_NLua_String()
@@ -43,11 +43,11 @@ public class NBodyBenchmark
         return core.NLuaState.DoString(core.SourceText);
         return core.NLuaState.DoString(core.SourceText);
     }
     }
 
 
-    // [Benchmark(Description = "NLua (DoFile)")]
-    // public object[] Benchmark_NLua_File()
-    // {
-    //     return core.NLuaState.DoFile(core.FilePath);
-    // }
+    [Benchmark(Description = "NLua (DoFile)")]
+    public object[] Benchmark_NLua_File()
+    {
+        return core.NLuaState.DoFile(core.FilePath);
+    }
 
 
     [Benchmark(Description = "Lua-CSharp (DoString)")]
     [Benchmark(Description = "Lua-CSharp (DoString)")]
     public async Task<LuaValue> Benchmark_LuaCSharp_String()
     public async Task<LuaValue> Benchmark_LuaCSharp_String()
@@ -56,10 +56,10 @@ public class NBodyBenchmark
         return buffer[0];
         return buffer[0];
     }
     }
 
 
-    // [Benchmark(Description = "Lua-CSharp (DoFileAsync)")]
-    // public async Task<LuaValue> Benchmark_LuaCSharp_File()
-    // {
-    //     await core.LuaCSharpState.DoFileAsync(core.FilePath, buffer);
-    //     return buffer[0];
-    // }
+    [Benchmark(Description = "Lua-CSharp (DoFileAsync)")]
+    public async Task<LuaValue> Benchmark_LuaCSharp_File()
+    {
+        await core.LuaCSharpState.DoFileAsync(core.FilePath, buffer);
+        return buffer[0];
+    }
 }
 }

+ 119 - 0
sandbox/Benchmark/hooked.lua

@@ -0,0 +1,119 @@
+debug.sethook(function ()
+end,"",1000000)
+sun = {}
+jupiter = {}
+saturn = {}
+uranus = {}
+neptune = {}
+
+local sqrt = math.sqrt
+
+local PI = 3.141592653589793
+local SOLAR_MASS = 4 * PI * PI
+local DAYS_PER_YEAR = 365.24
+sun.x = 0.0
+sun.y = 0.0
+sun.z = 0.0
+sun.vx = 0.0
+sun.vy = 0.0
+sun.vz = 0.0
+sun.mass = SOLAR_MASS
+jupiter.x = 4.84143144246472090e+00
+jupiter.y = -1.16032004402742839e+00
+jupiter.z = -1.03622044471123109e-01
+jupiter.vx = 1.66007664274403694e-03 * DAYS_PER_YEAR
+jupiter.vy = 7.69901118419740425e-03 * DAYS_PER_YEAR
+jupiter.vz = -6.90460016972063023e-05 * DAYS_PER_YEAR
+jupiter.mass = 9.54791938424326609e-04 * SOLAR_MASS
+saturn.x = 8.34336671824457987e+00
+saturn.y = 4.12479856412430479e+00
+saturn.z = -4.03523417114321381e-01
+saturn.vx = -2.76742510726862411e-03 * DAYS_PER_YEAR
+saturn.vy = 4.99852801234917238e-03 * DAYS_PER_YEAR
+saturn.vz = 2.30417297573763929e-05 * DAYS_PER_YEAR
+saturn.mass = 2.85885980666130812e-04 * SOLAR_MASS
+uranus.x = 1.28943695621391310e+01
+uranus.y = -1.51111514016986312e+01
+uranus.z = -2.23307578892655734e-01
+uranus.vx = 2.96460137564761618e-03 * DAYS_PER_YEAR
+uranus.vy = 2.37847173959480950e-03 * DAYS_PER_YEAR
+uranus.vz = -2.96589568540237556e-05 * DAYS_PER_YEAR
+uranus.mass = 4.36624404335156298e-05 * SOLAR_MASS
+neptune.x = 1.53796971148509165e+01
+neptune.y = -2.59193146099879641e+01
+neptune.z = 1.79258772950371181e-01
+neptune.vx = 2.68067772490389322e-03 * DAYS_PER_YEAR
+neptune.vy = 1.62824170038242295e-03 * DAYS_PER_YEAR
+neptune.vz = -9.51592254519715870e-05 * DAYS_PER_YEAR
+neptune.mass = 5.15138902046611451e-05 * SOLAR_MASS
+
+local bodies = { sun, jupiter, saturn, uranus, neptune }
+
+local function advance(bodies, nbody, dt)
+    for i = 1, nbody do
+        local bi = bodies[i]
+        local bix, biy, biz, bimass = bi.x, bi.y, bi.z, bi.mass
+        local bivx, bivy, bivz = bi.vx, bi.vy, bi.vz
+        for j = i + 1, nbody do
+            local bj = bodies[j]
+            local dx, dy, dz = bix - bj.x, biy - bj.y, biz - bj.z
+            local dist2 = dx * dx + dy * dy + dz * dz
+            local mag = sqrt(dist2)
+            mag = dt / (mag * dist2)
+            local bm = bj.mass * mag
+            bivx = bivx - (dx * bm)
+            bivy = bivy - (dy * bm)
+            bivz = bivz - (dz * bm)
+            bm = bimass * mag
+            bj.vx = bj.vx + (dx * bm)
+            bj.vy = bj.vy + (dy * bm)
+            bj.vz = bj.vz + (dz * bm)
+        end
+        bi.vx = bivx
+        bi.vy = bivy
+        bi.vz = bivz
+        bi.x = bix + dt * bivx
+        bi.y = biy + dt * bivy
+        bi.z = biz + dt * bivz
+    end
+end
+
+local function energy(bodies, nbody)
+    local e = 0
+    for i = 1, nbody do
+        local bi = bodies[i]
+        local vx, vy, vz, bim = bi.vx, bi.vy, bi.vz, bi.mass
+        e = e + (0.5 * bim * (vx * vx + vy * vy + vz * vz))
+        for j = i + 1, nbody do
+            local bj = bodies[j]
+            local dx, dy, dz = bi.x - bj.x, bi.y - bj.y, bi.z - bj.z
+            local distance = sqrt(dx * dx + dy * dy + dz * dz)
+            e = e - ((bim * bj.mass) / distance)
+        end
+    end
+    return e
+end
+
+local function offsetMomentum(b, nbody)
+    local px, py, pz = 0, 0, 0
+    for i = 1, nbody do
+        local bi = b[i]
+        local bim = bi.mass
+        px = px + (bi.vx * bim)
+        py = py + (bi.vy * bim)
+        pz = pz + (bi.vz * bim)
+    end
+    b[1].vx = -px / SOLAR_MASS
+    b[1].vy = -py / SOLAR_MASS
+    b[1].vz = -pz / SOLAR_MASS
+end
+
+local N = tonumber(arg and arg[1]) or 10000
+local nbody = #bodies
+
+offsetMomentum(bodies, nbody)
+energy(bodies, nbody)
+for i = 1, N do advance(bodies, nbody, 0.01) end
+energy(bodies, nbody)
+debug.sethook(function ()
+end,"",1000000)

+ 1 - 3
sandbox/ConsoleApp1/Program.cs

@@ -46,8 +46,6 @@ catch (Exception ex)
 {
 {
     if (ex is LuaCompileException luaCompileException)
     if (ex is LuaCompileException luaCompileException)
     {
     {
-        
-    
         Console.WriteLine("CompileError " + new string('-', 50));
         Console.WriteLine("CompileError " + new string('-', 50));
         Console.WriteLine(RustLikeExceptionHook.OnCatch(source, luaCompileException)); ;
         Console.WriteLine(RustLikeExceptionHook.OnCatch(source, luaCompileException)); ;
         Console.WriteLine(new string('-', 55));
         Console.WriteLine(new string('-', 55));
@@ -114,7 +112,7 @@ static void DebugChunk(Prototype chunk, int id)
     }
     }
 }
 }
 
 
-public class LuaRustLikeException(string message, Exception? innerException) : LuaException(message, innerException);
+public class LuaRustLikeException(string message, Exception? innerException) : Exception(message, innerException);
 
 
 class RustLikeExceptionHook //: ILuaCompileHook
 class RustLikeExceptionHook //: ILuaCompileHook
 {
 {

+ 3 - 19
src/Lua/LuaThread.cs

@@ -60,10 +60,10 @@ public abstract class LuaThread
 
 
     public LuaState State { get; protected set; } = null!;
     public LuaState State { get; protected set; } = null!;
     protected ThreadCoreData? CoreData = new();
     protected ThreadCoreData? CoreData = new();
-    internal BitFlags2 LineAndCountHookMask;
+    internal bool IsLineHookEnabled;
     internal BitFlags2 CallOrReturnHookMask;
     internal BitFlags2 CallOrReturnHookMask;
     internal bool IsInHook;
     internal bool IsInHook;
-    internal int HookCount;
+    internal long HookCount;
     internal int BaseHookCount;
     internal int BaseHookCount;
     internal int LastPc;
     internal int LastPc;
 
 
@@ -72,27 +72,11 @@ public abstract class LuaThread
 
 
     internal ILuaTracebackBuildable? CurrentException;
     internal ILuaTracebackBuildable? CurrentException;
     internal readonly ReversedStack<CallStackFrame> ExceptionTrace = new();
     internal readonly ReversedStack<CallStackFrame> ExceptionTrace = new();
-    
-    // internal bool CancelRequested;
-    // internal CancellationToken CancellationToken;
 
 
     public bool IsRunning => CallStackFrameCount != 0;
     public bool IsRunning => CallStackFrameCount != 0;
     internal LuaFunction? Hook { get; set; }
     internal LuaFunction? Hook { get; set; }
     public LuaStack Stack => CoreData!.Stack;
     public LuaStack Stack => CoreData!.Stack;
 
 
-    internal bool IsLineHookEnabled
-    {
-        get => LineAndCountHookMask.Flag0;
-        set => LineAndCountHookMask.Flag0 = value;
-    }
-
-    internal bool IsCountHookEnabled
-    {
-        get => LineAndCountHookMask.Flag1;
-        set => LineAndCountHookMask.Flag1 = value;
-    }
-
-
     internal bool IsCallHookEnabled
     internal bool IsCallHookEnabled
     {
     {
         get => CallOrReturnHookMask.Flag0;
         get => CallOrReturnHookMask.Flag0;
@@ -106,7 +90,7 @@ public abstract class LuaThread
     }
     }
 
 
     public int CallStackFrameCount => CoreData == null ? 0 : CoreData!.CallStack.Count;
     public int CallStackFrameCount => CoreData == null ? 0 : CoreData!.CallStack.Count;
-    
+
     internal LuaThreadAccess CurrentAccess => new(this, CurrentVersion);
     internal LuaThreadAccess CurrentAccess => new(this, CurrentVersion);
     public LuaThreadAccess TopLevelAccess => new(this, 0);
     public LuaThreadAccess TopLevelAccess => new(this, 0);
 
 

+ 2 - 2
src/Lua/Runtime/LuaVirtualMachine.Debug.cs

@@ -27,9 +27,9 @@ public static partial class LuaVirtualMachine
             bool countHookIsDone = false;
             bool countHookIsDone = false;
             var pc = context.Pc;
             var pc = context.Pc;
             var prototype = context.Prototype;
             var prototype = context.Prototype;
-            if (context.Thread.IsCountHookEnabled && --context.Thread.HookCount == 0)
+            if (context.Thread.HookCount == 0)
             {
             {
-                context.Thread.HookCount = context.Thread.BaseHookCount;
+                context.Thread.HookCount = context.Thread.BaseHookCount + 1;
 
 
                 var hook = context.Thread.Hook!;
                 var hook = context.Thread.Hook!;
 
 

+ 15 - 8
src/Lua/Runtime/LuaVirtualMachine.cs

@@ -1,6 +1,7 @@
 using System.Diagnostics.CodeAnalysis;
 using System.Diagnostics.CodeAnalysis;
 using System.Runtime.CompilerServices;
 using System.Runtime.CompilerServices;
 using Lua.Internal;
 using Lua.Internal;
+
 // ReSharper disable MethodHasAsyncOverload
 // ReSharper disable MethodHasAsyncOverload
 
 
 // ReSharper disable InconsistentNaming
 // ReSharper disable InconsistentNaming
@@ -267,14 +268,15 @@ public static partial class LuaVirtualMachine
                 pool.TryPush(this);
                 pool.TryPush(this);
             }
             }
         }
         }
+
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void ThrowIfCancellationRequested()
         public void ThrowIfCancellationRequested()
         {
         {
             if (!CancellationToken.IsCancellationRequested) return;
             if (!CancellationToken.IsCancellationRequested) return;
             Throw();
             Throw();
-                
+
             void Throw()
             void Throw()
-            { 
+            {
                 GetThreadWithCurrentPc(this).ThrowIfCancellationRequested(CancellationToken);
                 GetThreadWithCurrentPc(this).ThrowIfCancellationRequested(CancellationToken);
             }
             }
         }
         }
@@ -303,6 +305,9 @@ public static partial class LuaVirtualMachine
         return context.ExecuteClosureAsyncImpl();
         return context.ExecuteClosureAsyncImpl();
     }
     }
 
 
+    static long DummyHookCount = 0;
+    static bool DummyLineHookEnabled = false;
+
     static bool MoveNext(VirtualMachineExecutionContext context)
     static bool MoveNext(VirtualMachineExecutionContext context)
     {
     {
         try
         try
@@ -314,13 +319,14 @@ public static partial class LuaVirtualMachine
             var stack = context.Stack;
             var stack = context.Stack;
             stack.EnsureCapacity(frameBase + context.Prototype.MaxStackSize);
             stack.EnsureCapacity(frameBase + context.Prototype.MaxStackSize);
             ref var constHead = ref MemoryMarshalEx.UnsafeElementAt(context.Prototype.Constants, 0);
             ref var constHead = ref MemoryMarshalEx.UnsafeElementAt(context.Prototype.Constants, 0);
-            ref var lineAndCountHookMask = ref context.Thread.LineAndCountHookMask;
+            ref var lineHookFlag = ref (context.Thread.IsInHook ? ref DummyLineHookEnabled : ref context.Thread.IsLineHookEnabled);
+            ref var hookCount = ref (context.Thread.IsInHook ? ref DummyHookCount : ref context.Thread.HookCount);
             goto Loop;
             goto Loop;
         LineHook:
         LineHook:
 
 
             {
             {
                 context.LastHookPc = context.Pc;
                 context.LastHookPc = context.Pc;
-                if (!context.Thread.IsInHook && ExecutePerInstructionHook(context))
+                if (ExecutePerInstructionHook(context))
                 {
                 {
                     {
                     {
                         context.PostOperation = PostOperationType.Nop;
                         context.PostOperation = PostOperationType.Nop;
@@ -336,7 +342,7 @@ public static partial class LuaVirtualMachine
             {
             {
                 var instruction = Unsafe.Add(ref instructionsHead, ++context.Pc);
                 var instruction = Unsafe.Add(ref instructionsHead, ++context.Pc);
                 context.Instruction = instruction;
                 context.Instruction = instruction;
-                if (lineAndCountHookMask.Value != 0 && (context.Pc != context.LastHookPc))
+                if (--hookCount == 0 || (lineHookFlag && (context.Pc != context.LastHookPc)))
                 {
                 {
                     goto LineHook;
                     goto LineHook;
                 }
                 }
@@ -1197,12 +1203,13 @@ public static partial class LuaVirtualMachine
             thread.ThrowIfCancellationRequested(cancellationToken);
             thread.ThrowIfCancellationRequested(cancellationToken);
             return thread.Stack.Count - funcIndex;
             return thread.Stack.Count - funcIndex;
         }
         }
-        catch(OperationCanceledException  operationCanceledException)
+        catch (OperationCanceledException operationCanceledException)
         {
         {
-            if(operationCanceledException is not LuaCanceledException)
+            if (operationCanceledException is not LuaCanceledException)
             {
             {
                 throw new LuaCanceledException(thread, cancellationToken, operationCanceledException);
                 throw new LuaCanceledException(thread, cancellationToken, operationCanceledException);
             }
             }
+
             throw;
             throw;
         }
         }
         finally
         finally
@@ -1402,7 +1409,7 @@ public static partial class LuaVirtualMachine
 
 
         if (!stack.Get(RA).TryReadTable(out var table))
         if (!stack.Get(RA).TryReadTable(out var table))
         {
         {
-            throw new LuaRuntimeException(GetThreadWithCurrentPc(context),"internal error");
+            throw new LuaRuntimeException(GetThreadWithCurrentPc(context), "internal error");
         }
         }
 
 
         var count = instruction.B == 0
         var count = instruction.B == 0

+ 1 - 7
src/Lua/Standard/DebugLibrary.cs

@@ -417,7 +417,6 @@ public class DebugLibrary
         {
         {
             thread.HookCount = -1;
             thread.HookCount = -1;
             thread.BaseHookCount = 0;
             thread.BaseHookCount = 0;
-            thread.IsCountHookEnabled = false;
             thread.Hook = null;
             thread.Hook = null;
             thread.IsLineHookEnabled = false;
             thread.IsLineHookEnabled = false;
             thread.IsCallHookEnabled = false;
             thread.IsCallHookEnabled = false;
@@ -430,17 +429,12 @@ public class DebugLibrary
         {
         {
             var count = context.GetArgument<int>(argOffset + 2);
             var count = context.GetArgument<int>(argOffset + 2);
             thread.BaseHookCount = count;
             thread.BaseHookCount = count;
-            thread.HookCount = count;
-            if (count > 0)
-            {
-                thread.IsCountHookEnabled = true;
-            }
+            thread.HookCount = count + 1;
         }
         }
         else
         else
         {
         {
             thread.HookCount = 0;
             thread.HookCount = 0;
             thread.BaseHookCount = 0;
             thread.BaseHookCount = 0;
-            thread.IsCountHookEnabled = false;
         }
         }
 
 
         thread.IsLineHookEnabled = (mask.Contains('l'));
         thread.IsLineHookEnabled = (mask.Contains('l'));