DragonECS/src/Debug/EcsDebug.cs

215 lines
7.3 KiB
C#
Raw Normal View History

2024-02-14 03:04:05 +08:00
using DCFApixels.DragonECS.Internal;
using System;
2023-03-27 17:34:12 +08:00
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
2023-03-27 17:34:12 +08:00
namespace DCFApixels.DragonECS
{
public readonly struct EcsProfilerMarker
2023-03-30 06:03:05 +08:00
{
public readonly int id;
2023-06-10 18:15:09 +08:00
internal EcsProfilerMarker(int id) => this.id = id;
public EcsProfilerMarker(string name) => id = DebugService.Instance.RegisterMark(name);
2023-03-30 11:17:17 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2023-06-12 20:30:44 +08:00
public void Begin() => DebugService.Instance.ProfilerMarkBegin(id);
2023-03-30 11:17:17 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2023-06-12 20:30:44 +08:00
public void End() => DebugService.Instance.ProfilerMarkEnd(id);
2023-03-30 11:17:17 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public AutoScope Auto() => new AutoScope(id);
2023-04-01 20:45:37 +08:00
public readonly ref struct AutoScope
{
private readonly int _id;
public AutoScope(int id)
2023-03-30 06:03:05 +08:00
{
_id = id;
2023-06-12 20:30:44 +08:00
DebugService.Instance.ProfilerMarkBegin(id);
}
2023-06-12 20:30:44 +08:00
public void Dispose() => DebugService.Instance.ProfilerMarkEnd(_id);
2023-03-30 06:03:05 +08:00
}
}
2023-03-27 17:34:12 +08:00
public static class EcsDebug
{
2023-11-22 11:28:15 +08:00
public const string WARNING_TAG = EcsConsts.DEBUG_WARNING_TAG;
public const string ERROR_TAG = EcsConsts.DEBUG_ERROR_TAG;
2023-12-31 21:03:00 +08:00
public const string PASS_TAG = EcsConsts.DEBUG_PASS_TAG;
2023-11-22 11:28:15 +08:00
2023-03-27 17:34:12 +08:00
public static void Set<T>() where T : DebugService, new() => DebugService.Set<T>();
public static void Set(DebugService service) => DebugService.Set(service);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2023-05-27 15:59:46 +08:00
public static void PrintWarning(object v) => Print(EcsConsts.DEBUG_WARNING_TAG, v);
public static void PrintError(object v) => Print(EcsConsts.DEBUG_ERROR_TAG, v);
2024-02-03 01:12:53 +08:00
public static void PrintErrorAndBreak(object v)
{
Print(EcsConsts.DEBUG_ERROR_TAG, v);
Break();
}
2023-12-31 21:03:00 +08:00
public static void PrintPass(object v) => Print(EcsConsts.DEBUG_PASS_TAG, v);
2023-11-08 15:15:10 +08:00
public static void Print()
{
#if !DISABLE_DRAGONECS_DEBUGGER
DebugService.Instance.Print("");
#endif
}
2023-05-27 15:59:46 +08:00
public static void Print(object v)
{
#if !DISABLE_DRAGONECS_DEBUGGER
DebugService.Instance.Print(v);
#endif
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2023-03-27 17:34:12 +08:00
public static void Print(string tag, object v)
{
#if !DISABLE_DRAGONECS_DEBUGGER
2023-03-27 17:34:12 +08:00
DebugService.Instance.Print(tag, v);
#endif
}
2023-06-30 00:32:25 +08:00
public static void Break()
{
{
#if !DISABLE_DRAGONECS_DEBUGGER
DebugService.Instance.Break();
#endif
}
}
2023-03-27 17:34:12 +08:00
}
2023-03-30 06:03:05 +08:00
2023-03-27 17:34:12 +08:00
public abstract class DebugService
{
private static DebugService _instance;
2023-06-12 20:46:51 +08:00
public static DebugService Instance
{
get
{
if (_instance == null)
_instance = new DefaultDebugService();
return _instance;
}
}
2023-03-27 17:34:12 +08:00
public static void Set<T>() where T : DebugService, new() => Set(new T());
public static void Set(DebugService service)
{
_instance = service;
OnServiceChanged(_instance);
}
public static Action<DebugService> OnServiceChanged = delegate { };
2024-02-14 02:39:42 +08:00
private IdDispenser _idDispenser = new IdDispenser(4, -1);
2023-03-27 17:34:12 +08:00
private Dictionary<string, int> _nameIdTable = new Dictionary<string, int>();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2023-03-27 17:34:12 +08:00
public void Print(object v) => Print(null, v);
public abstract void Print(string tag, object v);
2023-06-30 00:31:17 +08:00
public abstract void Break();
2023-03-27 17:34:12 +08:00
public int RegisterMark(string name)
{
int id;
2023-05-30 18:30:10 +08:00
if (!_nameIdTable.TryGetValue(name, out id))
2023-03-27 17:34:12 +08:00
{
2024-02-14 02:39:42 +08:00
id = _idDispenser.UseFree();
2023-03-27 17:34:12 +08:00
_nameIdTable.Add(name, id);
}
2023-06-12 20:30:44 +08:00
OnNewProfilerMark(id, name);
2023-03-27 17:34:12 +08:00
return id;
}
public void DeleteMark(string name)
{
int id = _nameIdTable[name];
_nameIdTable.Remove(name);
_idDispenser.Release(id);
2023-06-12 20:30:44 +08:00
OnDelProfilerMark(id);
2023-03-27 17:34:12 +08:00
}
2023-06-12 20:30:44 +08:00
protected abstract void OnNewProfilerMark(int id, string name);
protected abstract void OnDelProfilerMark(int id);
2023-03-27 17:34:12 +08:00
2023-06-12 20:30:44 +08:00
public abstract void ProfilerMarkBegin(int id);
public abstract void ProfilerMarkEnd(int id);
2023-03-27 17:34:12 +08:00
}
public sealed class DefaultDebugService : DebugService
{
private Stopwatch[] _stopwatchs;
2023-03-30 16:39:16 +08:00
private string[] _stopwatchsNames;
2023-03-27 17:34:12 +08:00
public DefaultDebugService()
{
2023-11-22 11:38:28 +08:00
Console.ForegroundColor = ConsoleColor.White;
Console.BackgroundColor = ConsoleColor.Black;
#if !DISABLE_DRAGONECS_DEBUGGER
2023-03-27 17:34:12 +08:00
_stopwatchs = new Stopwatch[64];
2023-05-30 18:30:10 +08:00
_stopwatchsNames = new string[64];
2023-03-27 17:34:12 +08:00
#endif
}
2023-11-22 11:38:28 +08:00
2023-03-27 17:34:12 +08:00
public override void Print(string tag, object v)
{
2023-11-22 11:28:15 +08:00
if (string.IsNullOrEmpty(tag))
{
Console.WriteLine(v);
}
else
{
var color = Console.ForegroundColor;
switch (tag)
{
case EcsDebug.ERROR_TAG:
Console.ForegroundColor = ConsoleColor.Red;
break;
case EcsDebug.WARNING_TAG:
Console.ForegroundColor = ConsoleColor.Yellow;
break;
2023-12-31 21:03:00 +08:00
case EcsDebug.PASS_TAG:
Console.ForegroundColor = ConsoleColor.Green;
break;
2023-11-22 11:28:15 +08:00
}
Console.WriteLine($"[{tag}] {v}");
Console.ForegroundColor = color;
}
2023-03-27 17:34:12 +08:00
}
2023-06-30 00:31:17 +08:00
public override void Break()
{
2023-11-22 11:28:15 +08:00
var color = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine("Press Enter to сontinue.");
Console.ReadKey();
Console.ForegroundColor = color;
2023-06-30 00:31:17 +08:00
}
2023-06-12 20:30:44 +08:00
public override void ProfilerMarkBegin(int id)
2023-03-27 17:34:12 +08:00
{
var color = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.DarkGray;
2023-03-27 17:34:12 +08:00
_stopwatchs[id].Start();
Print("ProfilerMark", $"{_stopwatchsNames[id]} start <");
Console.ForegroundColor = color;
2023-03-27 17:34:12 +08:00
}
2023-06-12 20:30:44 +08:00
public override void ProfilerMarkEnd(int id)
2023-03-27 17:34:12 +08:00
{
2023-11-22 11:28:15 +08:00
var color = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.DarkGray;
2023-03-27 17:34:12 +08:00
_stopwatchs[id].Stop();
var time = _stopwatchs[id].Elapsed;
_stopwatchs[id].Reset();
Print("ProfilerMark", $"> {_stopwatchsNames[id]} s:{time.TotalSeconds}");
2023-11-22 11:28:15 +08:00
Console.ForegroundColor = color;
2023-03-27 17:34:12 +08:00
}
2023-06-12 20:30:44 +08:00
protected override void OnDelProfilerMark(int id)
2023-03-27 17:34:12 +08:00
{
_stopwatchs[id] = null;
}
2023-06-12 20:30:44 +08:00
protected override void OnNewProfilerMark(int id, string name)
2023-03-27 17:34:12 +08:00
{
2023-03-30 16:39:16 +08:00
if (id >= _stopwatchs.Length)
{
Array.Resize(ref _stopwatchs, _stopwatchs.Length << 1);
Array.Resize(ref _stopwatchsNames, _stopwatchsNames.Length << 1);
}
2023-03-27 17:34:12 +08:00
_stopwatchs[id] = new Stopwatch();
2023-03-30 16:39:16 +08:00
_stopwatchsNames[id] = name;
2023-03-27 17:34:12 +08:00
}
}
}