Initial commit: Unity WordConnect project
This commit is contained in:
@ -0,0 +1,115 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using VContainer.Internal;
|
||||
|
||||
namespace VContainer.Diagnostics
|
||||
{
|
||||
public sealed class DiagnosticsCollector
|
||||
{
|
||||
public string ScopeName { get; }
|
||||
|
||||
readonly List<DiagnosticsInfo> diagnosticsInfos = new List<DiagnosticsInfo>();
|
||||
readonly ThreadLocal<Stack<DiagnosticsInfo>> resolveCallStack
|
||||
= new ThreadLocal<Stack<DiagnosticsInfo>>(() => new Stack<DiagnosticsInfo>());
|
||||
|
||||
public DiagnosticsCollector(string scopeName)
|
||||
{
|
||||
ScopeName = scopeName;
|
||||
}
|
||||
|
||||
public IReadOnlyList<DiagnosticsInfo> GetDiagnosticsInfos()
|
||||
{
|
||||
return diagnosticsInfos;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
lock (diagnosticsInfos)
|
||||
{
|
||||
diagnosticsInfos.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public void TraceRegister(RegisterInfo registerInfo)
|
||||
{
|
||||
lock (diagnosticsInfos)
|
||||
{
|
||||
diagnosticsInfos.Add(new DiagnosticsInfo(ScopeName, registerInfo));
|
||||
}
|
||||
}
|
||||
|
||||
public void TraceBuild(RegistrationBuilder registrationBuilder, Registration registration)
|
||||
{
|
||||
lock (diagnosticsInfos)
|
||||
{
|
||||
foreach (var x in diagnosticsInfos)
|
||||
{
|
||||
if (x.RegisterInfo.RegistrationBuilder == registrationBuilder)
|
||||
{
|
||||
x.ResolveInfo = new ResolveInfo(registration);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public object TraceResolve(Registration registration, Func<Registration, object> resolving)
|
||||
{
|
||||
var current = DiagnositcsContext.FindByRegistration(registration);
|
||||
var owner = resolveCallStack.Value.Count > 0 ? resolveCallStack.Value.Peek() : null;
|
||||
|
||||
if (!(registration.Provider is CollectionInstanceProvider) && current != null && current != owner)
|
||||
{
|
||||
current.ResolveInfo.RefCount += 1;
|
||||
current.ResolveInfo.MaxDepth = current.ResolveInfo.MaxDepth < 0
|
||||
? resolveCallStack.Value.Count
|
||||
: Math.Max(current.ResolveInfo.MaxDepth, resolveCallStack.Value.Count);
|
||||
|
||||
owner?.Dependencies.Add(current);
|
||||
|
||||
resolveCallStack.Value.Push(current);
|
||||
var watch = Stopwatch.StartNew();
|
||||
var instance = resolving(registration);
|
||||
watch.Stop();
|
||||
resolveCallStack.Value.Pop();
|
||||
|
||||
SetResolveTime(current, watch.ElapsedMilliseconds);
|
||||
|
||||
if (!current.ResolveInfo.Instances.Contains(instance))
|
||||
{
|
||||
current.ResolveInfo.Instances.Add(instance);
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
return resolving(registration);
|
||||
}
|
||||
|
||||
private static void SetResolveTime(DiagnosticsInfo current, long elapsedMilliseconds)
|
||||
{
|
||||
var resolves = current.ResolveInfo.RefCount;
|
||||
var resolveTime = current.ResolveInfo.ResolveTime;
|
||||
|
||||
switch (current.ResolveInfo.Registration.Lifetime)
|
||||
{
|
||||
case Lifetime.Transient:
|
||||
resolveTime = (resolveTime * (resolves - 1) + elapsedMilliseconds) / resolves;
|
||||
break;
|
||||
case Lifetime.Scoped:
|
||||
case Lifetime.Singleton:
|
||||
if (elapsedMilliseconds > resolveTime)
|
||||
resolveTime = elapsedMilliseconds;
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
current.ResolveInfo.ResolveTime = resolveTime;
|
||||
}
|
||||
|
||||
public void NotifyContainerBuilt(IObjectResolver container)
|
||||
=> DiagnositcsContext.NotifyContainerBuilt(container);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 689fb82515a24c2887f2693a3a11010b
|
||||
timeCreated: 1632059581
|
||||
@ -0,0 +1,64 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace VContainer.Diagnostics
|
||||
{
|
||||
public static class DiagnositcsContext
|
||||
{
|
||||
static readonly Dictionary<string, DiagnosticsCollector> collectors
|
||||
= new Dictionary<string, DiagnosticsCollector>();
|
||||
|
||||
public static event Action<IObjectResolver> OnContainerBuilt;
|
||||
|
||||
public static DiagnosticsCollector GetCollector(string name)
|
||||
{
|
||||
lock (collectors)
|
||||
{
|
||||
if (!collectors.TryGetValue(name, out var collector))
|
||||
{
|
||||
collector = new DiagnosticsCollector(name);
|
||||
collectors.Add(name, collector);
|
||||
}
|
||||
return collector;
|
||||
}
|
||||
}
|
||||
|
||||
public static ILookup<string, DiagnosticsInfo> GetGroupedDiagnosticsInfos()
|
||||
{
|
||||
lock (collectors)
|
||||
{
|
||||
return collectors
|
||||
.SelectMany(x => x.Value.GetDiagnosticsInfos())
|
||||
.Where(x => x.ResolveInfo.MaxDepth <= 1)
|
||||
.ToLookup(x => x.ScopeName);
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<DiagnosticsInfo> GetDiagnosticsInfos()
|
||||
{
|
||||
lock (collectors)
|
||||
{
|
||||
return collectors.SelectMany(x => x.Value.GetDiagnosticsInfos());
|
||||
}
|
||||
}
|
||||
|
||||
public static void NotifyContainerBuilt(IObjectResolver container)
|
||||
{
|
||||
OnContainerBuilt?.Invoke(container);
|
||||
}
|
||||
|
||||
internal static DiagnosticsInfo FindByRegistration(Registration registration)
|
||||
{
|
||||
return GetDiagnosticsInfos().FirstOrDefault(x => x.ResolveInfo.Registration == registration);
|
||||
}
|
||||
|
||||
public static void RemoveCollector(string name)
|
||||
{
|
||||
lock (collectors)
|
||||
{
|
||||
collectors.Remove(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a87e62523cc246f2917f3ba78f7c6e99
|
||||
timeCreated: 1633441412
|
||||
@ -0,0 +1,18 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace VContainer.Diagnostics
|
||||
{
|
||||
public sealed class DiagnosticsInfo
|
||||
{
|
||||
public string ScopeName { get; }
|
||||
public RegisterInfo RegisterInfo { get; }
|
||||
public ResolveInfo ResolveInfo { get; set; }
|
||||
public List<DiagnosticsInfo> Dependencies { get; } = new List<DiagnosticsInfo>();
|
||||
|
||||
public DiagnosticsInfo(string scopeName, RegisterInfo registerInfo)
|
||||
{
|
||||
ScopeName = scopeName;
|
||||
RegisterInfo = registerInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: af9e78dd14ec4031998bbf9c34cc93ae
|
||||
timeCreated: 1633441316
|
||||
@ -0,0 +1,119 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Security;
|
||||
using System.Threading;
|
||||
|
||||
namespace VContainer.Diagnostics
|
||||
{
|
||||
public sealed class RegisterInfo
|
||||
{
|
||||
static bool displayFileNames = true;
|
||||
static int idSeed;
|
||||
|
||||
public int Id { get; }
|
||||
public RegistrationBuilder RegistrationBuilder { get; }
|
||||
public StackTrace StackTrace { get; }
|
||||
|
||||
StackFrame headLineStackFrame;
|
||||
|
||||
internal string formattedStackTrace = default; // cache field for internal use(Unity Editor, etc...)
|
||||
|
||||
public RegisterInfo(RegistrationBuilder registrationBuilder)
|
||||
{
|
||||
Id = Interlocked.Increment(ref idSeed);
|
||||
RegistrationBuilder = registrationBuilder;
|
||||
StackTrace = new StackTrace(true);
|
||||
headLineStackFrame = GetHeadlineFrame(StackTrace);
|
||||
}
|
||||
|
||||
public string GetFilename()
|
||||
{
|
||||
if (headLineStackFrame != null && displayFileNames && headLineStackFrame.GetILOffset() != -1)
|
||||
{
|
||||
try
|
||||
{
|
||||
return headLineStackFrame.GetFileName();
|
||||
}
|
||||
catch (NotSupportedException)
|
||||
{
|
||||
displayFileNames = false;
|
||||
}
|
||||
catch (SecurityException)
|
||||
{
|
||||
displayFileNames = false;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public int GetFileLineNumber()
|
||||
{
|
||||
if (headLineStackFrame != null && displayFileNames && headLineStackFrame.GetILOffset() != -1)
|
||||
{
|
||||
try
|
||||
{
|
||||
return headLineStackFrame.GetFileLineNumber();
|
||||
}
|
||||
catch (NotSupportedException)
|
||||
{
|
||||
displayFileNames = false;
|
||||
}
|
||||
catch (SecurityException)
|
||||
{
|
||||
displayFileNames = false;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public string GetScriptAssetPath()
|
||||
{
|
||||
var filename = GetFilename();
|
||||
if (filename == null)
|
||||
return "";
|
||||
var prefixIndex = filename.LastIndexOf("Assets/");
|
||||
return prefixIndex > 0 ? filename.Substring(prefixIndex) : "";
|
||||
}
|
||||
|
||||
public string GetHeadline()
|
||||
{
|
||||
if (headLineStackFrame == null)
|
||||
return "";
|
||||
|
||||
var method = headLineStackFrame.GetMethod();
|
||||
var filename = GetFilename();
|
||||
if (filename != null)
|
||||
{
|
||||
var lineNumber = GetFileLineNumber();
|
||||
return $"{method.DeclaringType?.FullName}.{method.Name} (at {Path.GetFileName(filename)}:{lineNumber})";
|
||||
}
|
||||
|
||||
var ilOffset = headLineStackFrame.GetILOffset();
|
||||
if (ilOffset != -1)
|
||||
{
|
||||
return $"{method.DeclaringType?.FullName}.{method.Name}(offset: {ilOffset})";
|
||||
}
|
||||
return $"{method.DeclaringType?.FullName}.{method.Name}";
|
||||
}
|
||||
|
||||
StackFrame GetHeadlineFrame(StackTrace stackTrace)
|
||||
{
|
||||
for (var i = 0; i < stackTrace.FrameCount; i++)
|
||||
{
|
||||
var sf = stackTrace.GetFrame(i);
|
||||
if (sf == null) continue;
|
||||
|
||||
var m = sf.GetMethod();
|
||||
if (m == null) continue;
|
||||
|
||||
if (m.DeclaringType == null) continue;
|
||||
if (m.DeclaringType.Namespace == null || !m.DeclaringType.Namespace.StartsWith("VContainer"))
|
||||
{
|
||||
return sf;
|
||||
}
|
||||
}
|
||||
return stackTrace.FrameCount > 0 ? stackTrace.GetFrame(0) : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4359f1f8bb3b4540835998a60eb93049
|
||||
timeCreated: 1633272541
|
||||
@ -0,0 +1,18 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace VContainer.Diagnostics
|
||||
{
|
||||
public sealed class ResolveInfo
|
||||
{
|
||||
public Registration Registration { get; }
|
||||
public List<object> Instances { get; } = new List<object>();
|
||||
public int MaxDepth { get; set; } = -1;
|
||||
public int RefCount { get; set; }
|
||||
public long ResolveTime { get; set; }
|
||||
|
||||
public ResolveInfo(Registration registration)
|
||||
{
|
||||
Registration = registration;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3f53a6c226cf4a04ae556c00dc477f4b
|
||||
timeCreated: 1633102576
|
||||
Reference in New Issue
Block a user