feat: add tracing points for the NDMF preview tracing system

This commit is contained in:
bd_ 2024-09-28 18:17:50 -07:00
parent b866628b24
commit f3f2de3337
4 changed files with 91 additions and 13 deletions

View File

@ -19,7 +19,7 @@
"dependencies": {} "dependencies": {}
}, },
"nadena.dev.ndmf": { "nadena.dev.ndmf": {
"version": "1.5.0-rc.8" "version": "1.5.0-rc.11"
} }
} }
} }

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using nadena.dev.ndmf.preview; using nadena.dev.ndmf.preview;
using nadena.dev.ndmf.preview.trace;
namespace nadena.dev.modular_avatar.core.editor namespace nadena.dev.modular_avatar.core.editor
{ {
@ -13,6 +14,7 @@ namespace nadena.dev.modular_avatar.core.editor
public Key Key; public Key Key;
public Value Value; public Value Value;
public string DebugName; public string DebugName;
public int Generation;
} }
private readonly string _debugName; private readonly string _debugName;
@ -20,6 +22,8 @@ namespace nadena.dev.modular_avatar.core.editor
private readonly Func<Value, Value, bool> _equalityComparer; private readonly Func<Value, Value, bool> _equalityComparer;
private readonly Dictionary<Key, CacheEntry> _cache = new(); private readonly Dictionary<Key, CacheEntry> _cache = new();
private static int _generation = 0;
public PropCache(string debugName, Func<ComputeContext, Key, Value> operatorFunc, public PropCache(string debugName, Func<ComputeContext, Key, Value> operatorFunc,
Func<Value, Value, bool> equalityComparer = null) Func<Value, Value, bool> equalityComparer = null)
{ {
@ -30,41 +34,97 @@ namespace nadena.dev.modular_avatar.core.editor
private static void InvalidateEntry(CacheEntry entry) private static void InvalidateEntry(CacheEntry entry)
{ {
var newGenContext = new ComputeContext("PropCache/" + entry.DebugName + " key " + entry.Key); var newGenContext = new ComputeContext("PropCache/" + entry.DebugName + " key " + FormatKey(entry.Key) + " gen=" + _generation++);
var newValue = entry.Owner._operator(newGenContext, entry.Key); var newValue = entry.Owner._operator(newGenContext, entry.Key);
if (entry.Owner._equalityComparer != null && entry.Owner._equalityComparer(entry.Value, newValue)) if (!entry.ObserverContext.IsInvalidated && entry.Owner._equalityComparer != null && entry.Owner._equalityComparer(entry.Value, newValue))
{ {
TraceBuffer.RecordTraceEvent(
"PropCache.InvalidateEntry",
(ev) => $"[PropCache/{ev.Arg0}] Value did not change, retaining result (new gen={ev.Arg1})",
entry.DebugName, entry.Generation
);
entry.GenerateContext = newGenContext; entry.GenerateContext = newGenContext;
entry.GenerateContext.InvokeOnInvalidate(entry, InvalidateEntry); entry.GenerateContext.InvokeOnInvalidate(entry, InvalidateEntry);
return; return;
} }
var trace = TraceBuffer.RecordTraceEvent(
"PropCache.InvalidateEntry",
(ev) => $"[PropCache/{ev.Arg0}] Value changed, invalidating",
entry.DebugName
);
entry.Owner._cache.Remove(entry.Key); entry.Owner._cache.Remove(entry.Key);
entry.ObserverContext.Invalidate(); using (trace.Scope()) entry.ObserverContext.Invalidate();
} }
public Value Get(ComputeContext context, Key key) public Value Get(ComputeContext context, Key key)
{ {
TraceEvent ev;
var formattedKey = FormatKey(key);
if (!_cache.TryGetValue(key, out var entry) || entry.GenerateContext.IsInvalidated) if (!_cache.TryGetValue(key, out var entry) || entry.GenerateContext.IsInvalidated)
{ {
var subContext = new ComputeContext("PropCache/" + _debugName + " key " + key); var curGen = _generation++;
var subContext = new ComputeContext("PropCache/" + _debugName + " key " + formattedKey + " gen=" + curGen);
entry = new CacheEntry entry = new CacheEntry
{ {
GenerateContext = subContext, GenerateContext = subContext,
ObserverContext = new ComputeContext("Observer for PropCache for key " + key), ObserverContext = new ComputeContext("Observer for PropCache/" + _debugName + " for key " +
formattedKey + " gen=" + curGen),
Owner = this, Owner = this,
Key = key, Key = key,
Value = _operator(subContext, key), DebugName = _debugName,
DebugName = _debugName Generation = curGen
}; };
ev = TraceBuffer.RecordTraceEvent(
"PropCache.Get",
(ev) =>
{
var entry_ = (CacheEntry)ev.Arg0;
return
$"[PropCache/{entry_.DebugName}] Cache miss for key {entry_.Key} gen={entry_.Generation} from context {ev.Arg1}";
},
entry, context
);
_cache[key] = entry; _cache[key] = entry;
using (ev.Scope())
subContext.InvokeOnInvalidate(entry, InvalidateEntry); {
entry.Value = _operator(subContext, key);
entry.GenerateContext.InvokeOnInvalidate(entry, InvalidateEntry);
}
}
else
{
ev = TraceBuffer.RecordTraceEvent(
"PropCache.Get",
(ev) =>
{
var entry_ = (CacheEntry) ev.Arg0;
return $"[PropCache/{entry_.DebugName}] Cache hit for key {entry_.Key} gen={entry_.Generation} from context {ev.Arg1}";
},
entry, context
);
} }
entry.ObserverContext.Invalidates(context); entry.ObserverContext.Invalidates(context);
return entry.Value; return entry.Value;
} }
private static string FormatKey(object obj)
{
if (obj is UnityEngine.Object unityObj)
{
return $"{unityObj.GetHashCode()}#{unityObj}";
}
else
{
return "" + obj;
}
}
} }
} }

View File

@ -5,6 +5,7 @@ using System.Linq;
using nadena.dev.modular_avatar.ui; using nadena.dev.modular_avatar.ui;
using nadena.dev.ndmf.localization; using nadena.dev.ndmf.localization;
using nadena.dev.ndmf.preview; using nadena.dev.ndmf.preview;
using nadena.dev.ndmf.preview.trace;
using UnityEditor; using UnityEditor;
using UnityEditor.UIElements; using UnityEditor.UIElements;
using UnityEngine; using UnityEngine;
@ -14,8 +15,8 @@ namespace nadena.dev.modular_avatar.core.editor.Simulator
{ {
internal class ROSimulator : EditorWindow, IHasCustomMenu internal class ROSimulator : EditorWindow, IHasCustomMenu
{ {
public static PublishedValue<ImmutableDictionary<string, float>> PropertyOverrides = new(null); public static PublishedValue<ImmutableDictionary<string, float>> PropertyOverrides = new(null, debugName: "ROSimulator.PropertyOverrides");
public static PublishedValue<ImmutableDictionary<string, ModularAvatarMenuItem>> MenuItemOverrides = new(null); public static PublishedValue<ImmutableDictionary<string, ModularAvatarMenuItem>> MenuItemOverrides = new(null, debugName: "ROSimulator.MenuItemOverrides");
internal static string ROOT_PATH = "Packages/nadena.dev.modular-avatar/Editor/ReactiveObjects/Simulator/"; internal static string ROOT_PATH = "Packages/nadena.dev.modular-avatar/Editor/ReactiveObjects/Simulator/";
private static string USS = ROOT_PATH + "ROSimulator.uss"; private static string USS = ROOT_PATH + "ROSimulator.uss";
@ -106,6 +107,14 @@ namespace nadena.dev.modular_avatar.core.editor.Simulator
private void UpdatePropertyOverride(string prop, bool? enable, float f_val) private void UpdatePropertyOverride(string prop, bool? enable, float f_val)
{ {
var trace = TraceBuffer.RecordTraceEvent(
"ROSimulator.UpdatePropertyOverride",
(ev) => $"Property {ev.Arg0} set to {ev.Arg1}",
arg0: prop,
arg1: enable == null ? "null" : enable.Value ? f_val : 0f
);
using (trace.Scope())
if (enable == null) if (enable == null)
{ {
PropertyOverrides.Value = PropertyOverrides.Value.Remove(prop); PropertyOverrides.Value = PropertyOverrides.Value.Remove(prop);
@ -123,6 +132,15 @@ namespace nadena.dev.modular_avatar.core.editor.Simulator
private void UpdateMenuItemOverride(string prop, ModularAvatarMenuItem item, bool? value) private void UpdateMenuItemOverride(string prop, ModularAvatarMenuItem item, bool? value)
{ {
var trace = TraceBuffer.RecordTraceEvent(
"ROSimulator.UpdateMenuItemOverride",
(ev) => $"MenuItem {ev.Arg0} for prop {ev.Arg1} set to {ev.Arg2}",
arg0: item.gameObject.name,
arg1: prop,
arg2: value == null ? "null" : value.Value ? "true" : "false"
);
using (trace.Scope())
if (value == null) if (value == null)
{ {
MenuItemOverrides.Value = MenuItemOverrides.Value.Remove(prop); MenuItemOverrides.Value = MenuItemOverrides.Value.Remove(prop);

View File

@ -16,6 +16,6 @@
}, },
"vpmDependencies": { "vpmDependencies": {
"com.vrchat.avatars": ">=3.7.0", "com.vrchat.avatars": ">=3.7.0",
"nadena.dev.ndmf": ">=1.5.0-rc.10 <2.0.0-a" "nadena.dev.ndmf": ">=1.5.0-rc.11 <2.0.0-a"
} }
} }