diff --git a/RuntimeUnityEditor.Core/Windows/Breakpoints/BreakpointHit.cs b/RuntimeUnityEditor.Core/Windows/Breakpoints/BreakpointHit.cs
index 35a76f4..acd3219 100644
--- a/RuntimeUnityEditor.Core/Windows/Breakpoints/BreakpointHit.cs
+++ b/RuntimeUnityEditor.Core/Windows/Breakpoints/BreakpointHit.cs
@@ -12,15 +12,21 @@ public sealed class BreakpointHit
///
/// Create a new breakpoint hit.
///
- public BreakpointHit(BreakpointPatchInfo origin, object instance, object[] args, object result, StackTrace trace)
+ public BreakpointHit(BreakpointPatchInfo origin, object instance, StackTrace trace)
{
Origin = origin;
Instance = instance;
- Args = args;
- Result = result;
Trace = trace;
TraceString = trace.ToString();
Time = DateTime.UtcNow;
+ _sw = Stopwatch.StartNew();
+ }
+
+ internal void Finalize(object[] args, object result)
+ {
+ ElapsedMilliseconds = _sw.ElapsedMilliseconds;
+ Args = args;
+ Result = result;
}
///
@@ -34,11 +40,11 @@ public BreakpointHit(BreakpointPatchInfo origin, object instance, object[] args,
///
/// The arguments that were passed to the method.
///
- public readonly object[] Args;
+ public object[] Args { get; private set; }
///
/// The result of the method call.
///
- public readonly object Result;
+ public object Result { get; private set; }
///
/// The stack trace at the time of the hit.
///
@@ -49,6 +55,12 @@ public BreakpointHit(BreakpointPatchInfo origin, object instance, object[] args,
///
public readonly DateTime Time;
+ private readonly Stopwatch _sw;
+ ///
+ /// Gets the total time the target method ran for, in milliseconds.
+ ///
+ public long ElapsedMilliseconds { get; private set; }
+
private string _toStr, _searchStr;
///
/// Returns a string that can be used to search for this breakpoint hit.
diff --git a/RuntimeUnityEditor.Core/Windows/Breakpoints/Breakpoints.cs b/RuntimeUnityEditor.Core/Windows/Breakpoints/Breakpoints.cs
index 0ac899e..a7c667a 100644
--- a/RuntimeUnityEditor.Core/Windows/Breakpoints/Breakpoints.cs
+++ b/RuntimeUnityEditor.Core/Windows/Breakpoints/Breakpoints.cs
@@ -12,8 +12,9 @@ namespace RuntimeUnityEditor.Core.Breakpoints
public static class Breakpoints
{
private static readonly Harmony _harmony = new Harmony("RuntimeUnityEditor.Core.Breakpoints");
- private static readonly HarmonyMethod _handlerMethodRet = new HarmonyMethod(typeof(Hooks), nameof(Hooks.BreakpointHandlerReturn));
- private static readonly HarmonyMethod _handlerMethodNoRet = new HarmonyMethod(typeof(Hooks), nameof(Hooks.BreakpointHandlerNoReturn));
+ private static readonly HarmonyMethod _handlerMethodPrefix = new HarmonyMethod(typeof(Hooks), nameof(Hooks.BreakpointHandlerPrefix)) { priority = Priority.First }; // wrap around other patches
+ private static readonly HarmonyMethod _handlerMethodRet = new HarmonyMethod(typeof(Hooks), nameof(Hooks.BreakpointHandlerReturn)) { priority = Priority.Last };
+ private static readonly HarmonyMethod _handlerMethodNoRet = new HarmonyMethod(typeof(Hooks), nameof(Hooks.BreakpointHandlerNoReturn)) { priority = Priority.Last };
private static readonly Dictionary _appliedPatches = new Dictionary();
///
/// A collection of all applied patches.
@@ -53,7 +54,7 @@ public static bool AttachBreakpoint(MethodBase target, object instance)
}
var hasReturn = target is MethodInfo mi && mi.ReturnType != typeof(void);
- var patch = _harmony.Patch(target, postfix: hasReturn ? _handlerMethodRet : _handlerMethodNoRet);
+ var patch = _harmony.Patch(target, prefix: _handlerMethodPrefix, postfix: hasReturn ? _handlerMethodRet : _handlerMethodNoRet);
if (patch != null)
{
_appliedPatches[target] = new BreakpointPatchInfo(target, patch, instance);
@@ -111,17 +112,24 @@ public static void DetachAll()
_appliedPatches.Clear();
}
- private static void AddHit(object __instance, MethodBase __originalMethod, object[] __args, object __result)
+ private static BreakpointHit BeginHit(object __instance, MethodBase __originalMethod)
{
- if (!Enabled) return;
+ if (!Enabled) return null;
- if (!_appliedPatches.TryGetValue(__originalMethod, out var pi)) return;
+ if (!_appliedPatches.TryGetValue(__originalMethod, out var pi)) return null;
- if (pi.InstanceFilters.Count > 0 && !pi.InstanceFilters.Contains(__instance)) return;
+ if (pi.InstanceFilters.Count > 0 && !pi.InstanceFilters.Contains(__instance)) return null;
+
+ return new BreakpointHit(pi, __instance, new StackTrace(2, true));
+ }
+
+ private static void EndHit(BreakpointHit hit, object[] __args, object __result)
+ {
+ hit.Finalize(__args, __result);
if (DebuggerBreaking == DebuggerBreakType.ThrowCatch)
{
- try { throw new BreakpointHitException(pi.Target.Name); }
+ try { throw new BreakpointHitException(hit.Origin.Target.Name); }
catch (BreakpointHitException) { }
}
else if (DebuggerBreaking == DebuggerBreakType.DebuggerBreak)
@@ -129,19 +137,26 @@ private static void AddHit(object __instance, MethodBase __originalMethod, objec
Debugger.Break();
}
- OnBreakpointHit?.Invoke(new BreakpointHit(pi, __instance, __args, __result, new StackTrace(2, true)));
+ OnBreakpointHit?.Invoke(hit);
}
private static class Hooks
{
- public static void BreakpointHandlerReturn(object __instance, MethodBase __originalMethod, object[] __args, object __result)
+ public static void BreakpointHandlerPrefix(object __instance, MethodBase __originalMethod, ref BreakpointHit __state)
+ {
+ __state = BeginHit(__instance, __originalMethod);
+ }
+
+ public static void BreakpointHandlerReturn(object[] __args, object __result, BreakpointHit __state)
{
- AddHit(__instance, __originalMethod, __args, __result);
+ if (__state != null)
+ EndHit(__state, __args, __result);
}
- public static void BreakpointHandlerNoReturn(object __instance, MethodBase __originalMethod, object[] __args)
+ public static void BreakpointHandlerNoReturn(object[] __args, BreakpointHit __state)
{
- AddHit(__instance, __originalMethod, __args, null);
+ if (__state != null)
+ EndHit(__state, __args, null);
}
}
}
diff --git a/RuntimeUnityEditor.Core/Windows/Breakpoints/BreakpointsWindow.cs b/RuntimeUnityEditor.Core/Windows/Breakpoints/BreakpointsWindow.cs
index 2f70fef..1732613 100644
--- a/RuntimeUnityEditor.Core/Windows/Breakpoints/BreakpointsWindow.cs
+++ b/RuntimeUnityEditor.Core/Windows/Breakpoints/BreakpointsWindow.cs
@@ -169,7 +169,7 @@ private void DrawHits()
GUILayout.BeginHorizontal(GUI.skin.box);
{
- GUILayout.Label($"{hit.Time:HH:mm:ss.fff}", GUILayout.Width(85));
+ GUILayout.Label($"{hit.Time:HH:mm:ss.fff}\nTook {hit.ElapsedMilliseconds}ms", GUILayout.Width(85));
DrawHitOriginButton(hit.Origin);