Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ jobs:
working-directory: src/
continue-on-error: false

- name: Run Performance Tests
run: |
dotnet test Libraries/ACATCore.Tests.Performance/ACATCore.Tests.Performance.csproj --configuration ${{ matrix.configuration }} --logger "trx;LogFileName=performance-tests.trx" --logger "console;verbosity=normal" --results-directory TestResults
working-directory: src/
continue-on-error: false

# Publish test results
- name: Publish Test Results
uses: dorny/test-reporter@v1
Expand Down
8 changes: 8 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,14 @@ jobs:
--results-directory TestResults/
working-directory: src/

- name: Run ACATCore.Tests.Performance
run: >
dotnet test Libraries/ACATCore.Tests.Performance/ACATCore.Tests.Performance.csproj
--configuration Debug
--logger "trx;LogFileName=performance-results.trx"
--results-directory TestResults/
working-directory: src/

- name: Upload test results
uses: actions/upload-artifact@v4
if: always()
Expand Down
19 changes: 19 additions & 0 deletions src/ACAT.sln
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ACATCore.Tests.Logging", "L
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ACATCore.Tests.Integration", "Libraries\ACATCore.Tests.Integration\ACATCore.Tests.Integration.csproj", "{55D58F6D-68E0-52D6-5909-E5772FA29551}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ACATCore.Tests.Performance", "Libraries\ACATCore.Tests.Performance\ACATCore.Tests.Performance.csproj", "{8B3C1A2D-4E5F-6789-ABCD-EF0123456789}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug_signed|Any CPU = Debug_signed|Any CPU
Expand Down Expand Up @@ -1218,6 +1220,23 @@ Global
{55D58F6D-68E0-52D6-5909-E5772FA29551}.Release|x64.Build.0 = Release|x64
{55D58F6D-68E0-52D6-5909-E5772FA29551}.Release|x86.ActiveCfg = Release|x64
{55D58F6D-68E0-52D6-5909-E5772FA29551}.Release|x86.Build.0 = Release|x64
{8B3C1A2D-4E5F-6789-ABCD-EF0123456789}.Debug_signed|Any CPU.ActiveCfg = Debug|Any CPU
{8B3C1A2D-4E5F-6789-ABCD-EF0123456789}.Debug_signed|x64.ActiveCfg = Debug|Any CPU
{8B3C1A2D-4E5F-6789-ABCD-EF0123456789}.Debug_signed|x86.ActiveCfg = Debug|Any CPU
{8B3C1A2D-4E5F-6789-ABCD-EF0123456789}.Debug_TestGTEC|Any CPU.ActiveCfg = Debug|Any CPU
{8B3C1A2D-4E5F-6789-ABCD-EF0123456789}.Debug_TestGTEC|x64.ActiveCfg = Debug|Any CPU
{8B3C1A2D-4E5F-6789-ABCD-EF0123456789}.Debug_TestGTEC|x86.ActiveCfg = Debug|Any CPU
{8B3C1A2D-4E5F-6789-ABCD-EF0123456789}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8B3C1A2D-4E5F-6789-ABCD-EF0123456789}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8B3C1A2D-4E5F-6789-ABCD-EF0123456789}.Debug|x64.ActiveCfg = Debug|Any CPU
{8B3C1A2D-4E5F-6789-ABCD-EF0123456789}.Debug|x86.ActiveCfg = Debug|Any CPU
{8B3C1A2D-4E5F-6789-ABCD-EF0123456789}.Release_signed|Any CPU.ActiveCfg = Release|Any CPU
{8B3C1A2D-4E5F-6789-ABCD-EF0123456789}.Release_signed|x64.ActiveCfg = Release|Any CPU
{8B3C1A2D-4E5F-6789-ABCD-EF0123456789}.Release_signed|x86.ActiveCfg = Release|Any CPU
{8B3C1A2D-4E5F-6789-ABCD-EF0123456789}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8B3C1A2D-4E5F-6789-ABCD-EF0123456789}.Release|Any CPU.Build.0 = Release|Any CPU
{8B3C1A2D-4E5F-6789-ABCD-EF0123456789}.Release|x64.ActiveCfg = Release|Any CPU
{8B3C1A2D-4E5F-6789-ABCD-EF0123456789}.Release|x86.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
41 changes: 41 additions & 0 deletions src/Applications/ACATTalk/PerformanceMonitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

#if PERFORMANCE

using ACAT.Core.Utility.Diagnostics;
using ACAT.Core.Utility.Metrics;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
Expand All @@ -27,6 +29,8 @@ namespace ACATTalk
/// <summary>
/// Provides performance monitoring and baseline metrics collection
/// for ACATTalk application. Only compiled when PERFORMANCE symbol is defined.
/// Integrates <see cref="RuntimeMetricsCollector"/>, <see cref="MemoryProfiler"/>,
/// and <see cref="PerformanceRegressionDetector"/> from the ACATCore library.
/// </summary>
public static class PerformanceMonitor
{
Expand All @@ -38,6 +42,11 @@ public static class PerformanceMonitor
private static Timer _memoryMonitor;
private static readonly object _reportLock = new object();

// ---- ACATCore performance infrastructure ----
private static readonly RuntimeMetricsCollector _runtimeCollector = new RuntimeMetricsCollector();
private static readonly MemoryProfiler _memoryProfiler = new MemoryProfiler();
private static PerformanceRegressionDetector _regressionDetector;

/// <summary>
/// Metric categories for organizing performance data
/// </summary>
Expand Down Expand Up @@ -65,6 +74,19 @@ public static void Initialize()
// Monitor memory every 5 seconds
_memoryMonitor = new Timer(MonitorMemory, null, TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(5));

// Start the ACATCore runtime metrics collector (5-second interval)
_runtimeCollector.Start(5000);

// Capture startup memory snapshot
_memoryProfiler.CaptureSnapshot("Startup");

// Load baseline (if present) or use defaults
string baselinePath = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"ACAT", "performance_baseline.json");
PerformanceBaselineData baseline = PerformanceBaseline.Load(baselinePath);
_regressionDetector = new PerformanceRegressionDetector(baseline);

LogEvent("PerformanceMonitor", "Performance monitoring initialized");
}

Expand Down Expand Up @@ -167,6 +189,7 @@ public static void Shutdown()
{
_applicationLifetime.Stop();
_memoryMonitor?.Dispose();
_runtimeCollector.Stop();

var process = Process.GetCurrentProcess();
long endWorkingSet = process.WorkingSet64;
Expand All @@ -177,6 +200,24 @@ public static void Shutdown()
RecordMetric("PeakMemoryUsage", _peakWorkingSet / (1024.0 * 1024.0), "MB", MetricCategory.Memory);
RecordMetric("MemoryGrowth", (endWorkingSet - _startWorkingSet) / (1024.0 * 1024.0), "MB", MetricCategory.Memory);

// Capture shutdown memory snapshot and check for regressions
MemorySnapshot shutdownSnap = _memoryProfiler.CaptureSnapshot("Shutdown");
if (_regressionDetector != null)
{
var observations = new Dictionary<string, double>(StringComparer.OrdinalIgnoreCase)
{
["TotalApplicationLifetime"] = _applicationLifetime.Elapsed.TotalSeconds * 1000,
["PeakWorkingSetMB"] = _peakWorkingSet / (1024.0 * 1024.0),
["ManagedHeapMB"] = shutdownSnap.ManagedHeapMB
};

IReadOnlyList<RegressionResult> regressions = _regressionDetector.DetectRegressions(observations);
foreach (RegressionResult r in regressions)
{
Debug.WriteLine($"[PerformanceMonitor] {r}");
}
}

GenerateReport();
}

Expand Down
10 changes: 10 additions & 0 deletions src/Extensions/ACAT.Extensions.UI/ACAT.Extensions.UI.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Diagnostics\PerformanceDashboard.xaml.cs">
<DependentUpon>PerformanceDashboard.xaml</DependentUpon>
</Compile>
<Compile Include="Dialogs\WindowMoveResizeScannerForm.cs" />
<Compile Include="Dialogs\WindowMoveResizeScannerForm.Designer.cs" />
<Compile Include="FontUtility.cs" />
Expand Down Expand Up @@ -141,6 +144,13 @@
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.3" />
<PackageReference Include="Serilog.Extensions.Logging.File" Version="3.0.0" />
<PackageReference Include="System.Text.Json" Version="10.0.3" />
</ItemGroup>
<ItemGroup>
<Page Include="Diagnostics\PerformanceDashboard.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
</ItemGroup>
<ItemGroup>
<PackageReference Update="System.Resources.Extensions" Version="10.0.3" />
Expand Down
Loading