Skip to content

Commit

Permalink
Feature/refactor instrumentation (#96)
Browse files Browse the repository at this point in the history
* Refactor instrumentation/stats to be less of a mess
* Move instrumentation classes to main library
* Add instrumentation tests
  • Loading branch information
highbyte authored Nov 29, 2023
1 parent e0ba1e5 commit dc177e6
Show file tree
Hide file tree
Showing 52 changed files with 780 additions and 743 deletions.
2 changes: 1 addition & 1 deletion src/apps/Highbyte.DotNet6502.App.ConsoleMonitor/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@
}
else
{
lastExecEvaluatorTriggerResult = systemRunner.RunEmulatorOneFrame(out _);
lastExecEvaluatorTriggerResult = systemRunner.RunEmulatorOneFrame();
if (lastExecEvaluatorTriggerResult.Triggered)
{
startMonitor = true;
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System.Numerics;
using Highbyte.DotNet6502.App.SilkNetNative.Instrumentation.Stats;
using Highbyte.DotNet6502.App.SilkNetNative.Stats;
using Highbyte.DotNet6502.Instrumentation.Stats;

namespace Highbyte.DotNet6502.App.SilkNetNative;

Expand All @@ -11,12 +10,15 @@ public class SilkNetImGuiStatsPanel : ISilkNetImGuiWindow

private const int POS_X = 600;
private const int POS_Y = 2;
private const int WIDTH = 400;
private const int WIDTH = 500;
private const int HEIGHT = 300;
static Vector4 s_LabelColor = new Vector4(0.7f, 0.7f, 0.7f, 1.0f);

public SilkNetImGuiStatsPanel()
private readonly Func<List<(string Name, IStat Stat)>> _getStats;

public SilkNetImGuiStatsPanel(Func<List<(string name, IStat stat)>> getStats)
{
_getStats = getStats;
}

public void PostOnRender()
Expand All @@ -28,7 +30,7 @@ public void PostOnRender()
//ImGui.SetWindowSize(new Vector2(WIDTH, HEIGHT));

var strings = new List<string>();
foreach ((string name, IStat stat) in InstrumentationBag.Stats.OrderBy(i => i.Name))
foreach ((string name, IStat stat) in _getStats().OrderBy(i => i.Name))
{
if (stat.ShouldShow())
{
Expand Down
108 changes: 28 additions & 80 deletions src/apps/Highbyte.DotNet6502.App.SilkNetNative/SilkNetWindow.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
using System.Collections.Generic;
using AutoMapper;
using Highbyte.DotNet6502.App.SilkNetNative;
using Highbyte.DotNet6502.App.SilkNetNative.Instrumentation.Stats;
using Highbyte.DotNet6502.App.SilkNetNative.Stats;
using Highbyte.DotNet6502.Impl.NAudio;
using Highbyte.DotNet6502.Impl.NAudio.NAudioOpenALProvider;
using Highbyte.DotNet6502.Impl.SilkNet;
using Highbyte.DotNet6502.Impl.Skia;
using Highbyte.DotNet6502.Instrumentation;
using Highbyte.DotNet6502.Instrumentation.Stats;
using Highbyte.DotNet6502.Logging;
using Highbyte.DotNet6502.Monitor;
using Highbyte.DotNet6502.Systems;
Expand Down Expand Up @@ -54,16 +52,17 @@ public float CanvasScale

public EmulatorState EmulatorState { get; set; } = EmulatorState.Uninitialized;

private readonly ElapsedMillisecondsTimedStat _inputTime = InstrumentationBag.Add<ElapsedMillisecondsTimedStat>("SilkNet-InputTime");
private readonly ElapsedMillisecondsTimedStat _systemTime = InstrumentationBag.Add<ElapsedMillisecondsTimedStat>("Emulator-SystemTime");
private readonly ElapsedMillisecondsStat _systemTimeAudio = InstrumentationBag.Add<ElapsedMillisecondsStat>("Emulator-SystemTime-Audio"); // Detailed part of system time
private readonly ElapsedMillisecondsTimedStat _renderTime = InstrumentationBag.Add<ElapsedMillisecondsTimedStat>("SilkNet-RenderTime");
private readonly PerSecondTimedStat _updateFps = InstrumentationBag.Add<PerSecondTimedStat>("SilkNet-OnUpdateFPS");
private readonly PerSecondTimedStat _renderFps = InstrumentationBag.Add<PerSecondTimedStat>("SilkNet-OnRenderFPS");

private const string CustomSystemStatNamePrefix = "Emulator-SystemTime-Custom-";
private const string CustomRenderStatNamePrefix = "SilkNet-RenderTime-Custom-";
private Dictionary<string, ElapsedMillisecondsStat> _customStats = new();
private const string HostStatRootName = "SilkNet";
private const string SystemTimeStatName = "Emulator-SystemTime";
private const string RenderTimeStatName = "RenderTime";
private const string InputTimeStatName = "InputTime";
private const string AudioTimeStatName = "AudioTime";
private readonly ElapsedMillisecondsTimedStat _systemTime = InstrumentationBag.Add<ElapsedMillisecondsTimedStat>($"{HostStatRootName}-{SystemTimeStatName}");
private readonly ElapsedMillisecondsTimedStat _renderTime = InstrumentationBag.Add<ElapsedMillisecondsTimedStat>($"{HostStatRootName}-{RenderTimeStatName}");
private readonly ElapsedMillisecondsTimedStat _inputTime = InstrumentationBag.Add<ElapsedMillisecondsTimedStat>($"{HostStatRootName}-{InputTimeStatName}");
//private readonly ElapsedMillisecondsTimedStat _audioTime = InstrumentationBag.Add<ElapsedMillisecondsTimedStat>($"{HostStatRootName}-AudioTimeStatName}");
private readonly PerSecondTimedStat _updateFps = InstrumentationBag.Add<PerSecondTimedStat>($"{HostStatRootName}-OnUpdateFPS");
private readonly PerSecondTimedStat _renderFps = InstrumentationBag.Add<PerSecondTimedStat>($"{HostStatRootName}-OnRenderFPS");

// Render context container for SkipSharp (surface/canvas) and SilkNetOpenGl
private SilkNetRenderContextContainer _silkNetRenderContextContainer;
Expand All @@ -80,7 +79,7 @@ public float CanvasScale
private SilkNetImGuiMonitor _monitor;
public SilkNetImGuiMonitor Monitor => _monitor;

// Stats panel
// Instrumentations panel
private SilkNetImGuiStatsPanel _statsPanel;
public SilkNetImGuiStatsPanel StatsPanel => _statsPanel;

Expand Down Expand Up @@ -168,7 +167,7 @@ protected void OnLoad()

protected void OnClosing()
{
// Dispose Monitor/Stats panel
// Dispose Monitor/Instrumentations panel
// _monitor.Cleanup();
// _statsPanel.Cleanup();
DestroyImGuiController();
Expand Down Expand Up @@ -249,33 +248,6 @@ public void SetCurrentSystem(string systemName)
}
}

private void InitCustomSystemStats()
{
// Remove any existing custom system stats
foreach (var existingCustomStatName in _customStats.Keys)
{
if (existingCustomStatName.StartsWith(CustomSystemStatNamePrefix)
|| existingCustomStatName.StartsWith(CustomRenderStatNamePrefix))
{
InstrumentationBag.Remove(existingCustomStatName);
_customStats.Remove(existingCustomStatName);
}
}
// Add any custom system stats for selected system
var system = _systemRunner.System;
foreach (var customStatName in system.DetailedStatNames)
{
_customStats.Add($"{CustomSystemStatNamePrefix}{customStatName}", InstrumentationBag.Add<ElapsedMillisecondsStat>($"{CustomSystemStatNamePrefix}{customStatName}"));
}

// Add any custom system stats for selected renderer
var renderer = _systemRunner.Renderer;
foreach (var customStatName in renderer.DetailedStatNames)
{
_customStats.Add($"{CustomRenderStatNamePrefix}{customStatName}", InstrumentationBag.Add<ElapsedMillisecondsStat>($"{CustomRenderStatNamePrefix}{customStatName}"));
}
}

public void SetVolumePercent(float volumePercent)
{
_defaultAudioVolumePercent = volumePercent;
Expand All @@ -294,8 +266,6 @@ public void Start()
if (EmulatorState == EmulatorState.Uninitialized)
_systemRunner = _systemList.BuildSystemRunner(_currentSystemName).Result;

InitCustomSystemStats();

_monitor.Init(_systemRunner!);

_systemRunner!.AudioHandler.StartPlaying();
Expand Down Expand Up @@ -364,25 +334,7 @@ private void RunEmulator()
ExecEvaluatorTriggerResult execEvaluatorTriggerResult;
using (_systemTime.Measure())
{
execEvaluatorTriggerResult = _systemRunner.RunEmulatorOneFrame(out var detailedStats);

if (detailedStats.ContainsKey("Audio"))
{
_systemTimeAudio.Set(detailedStats["Audio"]);
_systemTimeAudio.UpdateStat();
}

// Update custom system stats
// TODO: Make custom system stats less messy?
foreach (var detailedStatName in detailedStats.Keys)
{
var statLookup = _customStats.Keys.SingleOrDefault(x => x.EndsWith(detailedStatName));
if (statLookup != null)
{
_customStats[$"{CustomSystemStatNamePrefix}{detailedStatName}"].Set(detailedStats[detailedStatName]);
_customStats[$"{CustomSystemStatNamePrefix}{detailedStatName}"].UpdateStat();
}
}
execEvaluatorTriggerResult = _systemRunner.RunEmulatorOneFrame();
}

// Show monitor if we encounter breakpoint or other break
Expand Down Expand Up @@ -419,28 +371,14 @@ private void RenderEmulator(double deltaTime)
using (_renderTime.Measure())
{
// Render emulator system screen
_systemRunner!.Draw(out var detailedStats);
_systemRunner!.Draw();

// Flush the SkiaSharp Context
_silkNetRenderContextContainer.SkiaRenderContext.GetGRContext().Flush();

// Update custom system stats
// TODO: Make custom system stats less messy?
foreach (var detailedStatName in detailedStats.Keys)
{
var statLookup = _customStats.Keys.SingleOrDefault(x => x.EndsWith(detailedStatName));
if (statLookup != null)
{
_customStats[$"{CustomRenderStatNamePrefix}{detailedStatName}"].Set(detailedStats[detailedStatName]);
_customStats[$"{CustomRenderStatNamePrefix}{detailedStatName}"].UpdateStat();
}
}

}
emulatorRendered = true;



// SilkNet windows are what's known as "double-buffered". In essence, the window manages two buffers.
// One is rendered to while the other is currently displayed by the window.
// This avoids screen tearing, a visual artifact that can happen if the buffer is modified while being displayed.
Expand Down Expand Up @@ -545,7 +483,17 @@ private SilkNetImGuiMonitor CreateMonitorUI(SilkNetImGuiStatsPanel statsPanel, M

private SilkNetImGuiStatsPanel CreateStatsUI()
{
return new SilkNetImGuiStatsPanel();
return new SilkNetImGuiStatsPanel(GetStats);
}

private List<(string name, IStat stat)> GetStats()
{
return InstrumentationBag.Stats
.Union(_systemRunner.System.Instrumentations.Stats.Select(x => (Name: $"{HostStatRootName}-{SystemTimeStatName}-{x.Name}", x.Stat)))
.Union(_systemRunner.Renderer.Instrumentations.Stats.Select(x => (Name: $"{HostStatRootName}-{RenderTimeStatName}-{x.Name}", x.Stat)))
.Union(_systemRunner.AudioHandler.Instrumentations.Stats.Select(x => (Name: $"{HostStatRootName}-{AudioTimeStatName}-{x.Name}", x.Stat)))
.Union(_systemRunner.InputHandler.Instrumentations.Stats.Select(x => (Name: $"{HostStatRootName}-{InputTimeStatName}-{x.Name}", x.Stat)))
.ToList();
}

private SilkNetImGuiLogsPanel CreateLogsUI(DotNet6502InMemLogStore logStore, DotNet6502InMemLoggerConfiguration logConfig)
Expand Down

This file was deleted.

Loading

0 comments on commit dc177e6

Please sign in to comment.