Skip to content

Commit e1af4d9

Browse files
committed
Remove hidden diagnostics startup and tray cost
1 parent 1aa95e2 commit e1af4d9

10 files changed

Lines changed: 466 additions & 85 deletions

MainWindow.Behaviors.partial.cs

Lines changed: 29 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,6 @@ private void SetDataContexts()
4949
// Set DataContext for the association view
5050
this.AssociationView.DataContext = this.associationViewModel;
5151

52-
// Set DataContext for the performance view
53-
this.PerformanceViewControl.DataContext = this.performanceViewModel;
54-
5552
// Set DataContext for the log viewer view
5653
this.LogViewerViewControl.DataContext = this.logViewerViewModel;
5754

@@ -1001,57 +998,7 @@ private async Task UpdateSystemTrayContextMenuAsync()
1001998
{
1002999
try
10031000
{
1004-
// Update power plans in system tray
1005-
var powerPlanService = this.serviceProvider.GetRequiredService<IPowerPlanService>();
1006-
var powerPlans = await powerPlanService.GetPowerPlansAsync();
1007-
var activePowerPlan = await powerPlanService.GetActivePowerPlan();
1008-
this.systemTrayService.UpdatePowerPlans(powerPlans, activePowerPlan);
1009-
1010-
// Update profiles in system tray
1011-
var profilesDirectory = StoragePaths.ProfilesDirectory;
1012-
var profileNames = new List<string>();
1013-
1014-
if (Directory.Exists(profilesDirectory))
1015-
{
1016-
profileNames = Directory.GetFiles(profilesDirectory, "*.json")
1017-
.Select(Path.GetFileNameWithoutExtension)
1018-
.Where(name => !string.IsNullOrWhiteSpace(name))
1019-
.ToList()!;
1020-
}
1021-
1022-
this.systemTrayService.UpdateProfiles(profileNames);
1023-
1024-
// Update system status (with timeout to prevent hanging)
1025-
try
1026-
{
1027-
var performanceService = this.serviceProvider.GetRequiredService<IPerformanceMonitoringService>();
1028-
var metricsTask = performanceService.GetSystemMetricsAsync(lightweight: true);
1029-
var metricsResult = await Task.WhenAny(metricsTask, Task.Delay(2000)); // 2 second timeout
1030-
1031-
if (metricsResult == metricsTask)
1032-
{
1033-
var currentMetrics = await metricsTask;
1034-
this.systemTrayService.UpdateSystemStatus(
1035-
activePowerPlan?.Name ?? "Unknown",
1036-
currentMetrics?.TotalCpuUsage ?? 0.0,
1037-
currentMetrics?.MemoryUsagePercentage ?? 0.0);
1038-
}
1039-
else
1040-
{
1041-
// Timeout - use default values
1042-
this.systemTrayService.UpdateSystemStatus(
1043-
activePowerPlan?.Name ?? "Unknown",
1044-
0.0, 0.0);
1045-
}
1046-
}
1047-
catch (Exception metricsEx)
1048-
{
1049-
System.Diagnostics.Debug.WriteLine($"Failed to get performance metrics for tray: {metricsEx.Message}");
1050-
// Use default values
1051-
this.systemTrayService.UpdateSystemStatus(
1052-
activePowerPlan?.Name ?? "Unknown",
1053-
0.0, 0.0);
1054-
}
1001+
await this.systemTrayStatusUpdater.UpdateContextMenuAsync(this.systemTrayService);
10551002
}
10561003
catch (Exception ex)
10571004
{
@@ -1065,6 +1012,12 @@ private void StartSystemTrayUpdateTimer()
10651012
{
10661013
this.systemTrayUpdateTimer?.Stop();
10671014
this.systemTrayUpdateTimer?.Dispose();
1015+
this.systemTrayUpdateTimer = null;
1016+
1017+
if (!this.systemTrayStatusUpdater.ShouldRunPerformanceStatusUpdates)
1018+
{
1019+
return;
1020+
}
10681021

10691022
this.systemTrayUpdateFailureStreak = 0;
10701023
this.systemTrayUpdateTimer = new System.Timers.Timer(SystemTrayUpdateBaseIntervalMs);
@@ -1142,21 +1095,9 @@ private async Task<bool> UpdateSystemTrayStatusAsync()
11421095
{
11431096
try
11441097
{
1145-
var powerPlanService = this.serviceProvider.GetRequiredService<IPowerPlanService>();
1146-
var performanceService = this.serviceProvider.GetRequiredService<IPerformanceMonitoringService>();
1147-
1148-
var activePowerPlan = await powerPlanService.GetActivePowerPlan();
1149-
var currentMetrics = await performanceService.GetSystemMetricsAsync(lightweight: true);
1150-
1151-
await this.Dispatcher.InvokeAsync(() =>
1152-
{
1153-
this.systemTrayService.UpdateSystemStatus(
1154-
activePowerPlan?.Name ?? "Unknown",
1155-
currentMetrics?.TotalCpuUsage ?? 0.0,
1156-
currentMetrics?.MemoryUsagePercentage ?? 0.0);
1157-
});
1158-
1159-
return true;
1098+
return await this.systemTrayStatusUpdater.UpdateStatusAsync(
1099+
this.systemTrayService,
1100+
action => this.Dispatcher.InvokeAsync(action).Task);
11601101
}
11611102
catch (Exception ex)
11621103
{
@@ -1335,6 +1276,12 @@ private void ResumeForegroundRefreshes()
13351276
this.isSystemTrayUpdatesSuspended = false;
13361277
this.systemTrayUpdateFailureStreak = 0;
13371278
this.systemTrayUpdateTimer?.Stop();
1279+
1280+
if (!this.systemTrayStatusUpdater.ShouldRunPerformanceStatusUpdates)
1281+
{
1282+
return;
1283+
}
1284+
13381285
if (this.systemTrayUpdateTimer != null)
13391286
{
13401287
this.systemTrayUpdateTimer.Interval = SystemTrayUpdateBaseIntervalMs;
@@ -1405,9 +1352,9 @@ private void ApplyAppRefreshPolicy(AppActivityState state)
14051352

14061353
if (decision.PerformanceUiMonitoringEnabled)
14071354
{
1408-
_ = this.performanceViewModel.ActivateDiagnosticsAsync();
1355+
_ = this.GetPerformanceViewModel().ActivateDiagnosticsAsync();
14091356
}
1410-
else
1357+
else if (this.performanceViewModel != null)
14111358
{
14121359
_ = this.performanceViewModel.SuspendBackgroundMonitoringAsync();
14131360
}
@@ -1538,6 +1485,11 @@ private void SelectMainTab(string tag)
15381485
return;
15391486
}
15401487

1488+
if (string.Equals(tag, "Performance", StringComparison.Ordinal))
1489+
{
1490+
this.GetPerformanceViewModel();
1491+
}
1492+
15411493
this.ApplySectionVisibility(tag);
15421494

15431495
if (string.Equals(tag, "Performance", StringComparison.Ordinal))
@@ -1842,6 +1794,11 @@ private async Task NavMenuItem_ClickAsync(object sender, RoutedEventArgs e)
18421794
return;
18431795
}
18441796

1797+
if (string.Equals(tag, "Performance", StringComparison.Ordinal))
1798+
{
1799+
this.GetPerformanceViewModel();
1800+
}
1801+
18451802
this.ApplySectionVisibility(tag);
18461803

18471804
if (string.Equals(tag, "Performance", StringComparison.Ordinal))
@@ -1897,6 +1854,7 @@ protected override void OnClosed(EventArgs e)
18971854

18981855
this.initializationTimeoutTimer?.Stop();
18991856
this.initializationTimeoutTimer?.Dispose();
1857+
this.performanceViewModel?.Dispose();
19001858

19011859
this.selfResourceManagementService.RestoreForegroundMode();
19021860
this.navigationBehavior.Dispose();

MainWindow.xaml.cs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,11 @@ public partial class MainWindow : Wpf.Ui.Controls.FluentWindow
4242

4343
private readonly ProcessViewModel processViewModel;
4444
private readonly PowerPlanViewModel powerPlanViewModel;
45-
private readonly PerformanceViewModel performanceViewModel;
45+
private readonly IDiagnosticsViewModelProvider diagnosticsViewModelProvider;
4646
private readonly ProcessPowerPlanAssociationViewModel associationViewModel;
4747
private readonly LogViewerViewModel logViewerViewModel;
4848
private readonly ISystemTrayService systemTrayService;
49+
private readonly ISystemTrayStatusUpdater systemTrayStatusUpdater;
4950
private readonly IApplicationSettingsService settingsService;
5051
private readonly INotificationService notificationService;
5152
private readonly IProcessMonitorService processMonitorService;
@@ -59,6 +60,7 @@ public partial class MainWindow : Wpf.Ui.Controls.FluentWindow
5960
private readonly IServiceProvider serviceProvider;
6061
private readonly IThemeService themeService;
6162
private System.Timers.Timer? systemTrayUpdateTimer;
63+
private PerformanceViewModel? performanceViewModel;
6264
private bool isSystemTrayUpdatesSuspended;
6365
private int isSystemTrayUpdateInProgress;
6466
private int systemTrayUpdateFailureStreak;
@@ -84,10 +86,11 @@ public partial class MainWindow : Wpf.Ui.Controls.FluentWindow
8486
public MainWindow(
8587
ProcessViewModel processViewModel,
8688
PowerPlanViewModel powerPlanViewModel,
87-
PerformanceViewModel performanceViewModel,
89+
IDiagnosticsViewModelProvider diagnosticsViewModelProvider,
8890
ProcessPowerPlanAssociationViewModel associationViewModel,
8991
LogViewerViewModel logViewerViewModel,
9092
ISystemTrayService systemTrayService,
93+
ISystemTrayStatusUpdater systemTrayStatusUpdater,
9194
IApplicationSettingsService settingsService,
9295
INotificationService notificationService,
9396
IProcessMonitorService processMonitorService,
@@ -118,10 +121,11 @@ public MainWindow(
118121

119122
this.processViewModel = processViewModel;
120123
this.powerPlanViewModel = powerPlanViewModel;
121-
this.performanceViewModel = performanceViewModel;
124+
this.diagnosticsViewModelProvider = diagnosticsViewModelProvider;
122125
this.associationViewModel = associationViewModel;
123126
this.logViewerViewModel = logViewerViewModel;
124127
this.systemTrayService = systemTrayService;
128+
this.systemTrayStatusUpdater = systemTrayStatusUpdater;
125129
this.settingsService = settingsService;
126130
this.notificationService = notificationService;
127131
this.processMonitorService = processMonitorService;
@@ -167,5 +171,17 @@ private void ConfigureDiagnosticsNavigation()
167171
? Visibility.Visible
168172
: Visibility.Collapsed;
169173
}
174+
175+
private PerformanceViewModel GetPerformanceViewModel()
176+
{
177+
if (this.performanceViewModel != null)
178+
{
179+
return this.performanceViewModel;
180+
}
181+
182+
this.performanceViewModel = this.diagnosticsViewModelProvider.GetOrCreate();
183+
this.PerformanceViewControl.DataContext = this.performanceViewModel;
184+
return this.performanceViewModel;
185+
}
170186
}
171187
}

Services/ISystemTrayService.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,11 @@ public interface ISystemTrayService : IDisposable
138138
/// <summary>
139139
/// Updates the current system status in the tray.
140140
/// </summary>
141+
void UpdateSystemStatus(string currentPowerPlan);
142+
143+
/// <summary>
144+
/// Updates the current system status in the tray with diagnostics metrics.
145+
/// </summary>
141146
void UpdateSystemStatus(string currentPowerPlan, double cpuUsage, double memoryUsage);
142147
}
143148

Services/PerformanceMonitoringService.cs

Lines changed: 62 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,9 @@ public class PerformanceMonitoringService : IPerformanceMonitoringService, IDisp
3737
private readonly IApplicationSettingsService settingsService;
3838
private readonly IEnhancedLoggingService enhancedLoggingService;
3939
private readonly Queue<SystemPerformanceMetrics> historicalData;
40-
private readonly PerformanceCounter totalCpuCounter;
41-
private readonly PerformanceCounter memoryCounter;
40+
private readonly object counterInitializationLock = new();
41+
private PerformanceCounter? totalCpuCounter;
42+
private PerformanceCounter? memoryCounter;
4243
private readonly List<PerformanceCounter> cpuCoreCounters;
4344
private System.Threading.Timer? monitoringTimer;
4445
private readonly object totalMemoryCacheLock = new();
@@ -81,13 +82,7 @@ public PerformanceMonitoringService(
8182
this.settingsService = settingsService;
8283
this.enhancedLoggingService = enhancedLoggingService;
8384
this.historicalData = new Queue<SystemPerformanceMetrics>(HistoricalDataCapacity);
84-
85-
// Initialize performance counters
86-
this.totalCpuCounter = this.CreatePrimedCounter("Processor", "% Processor Time", "_Total");
87-
this.memoryCounter = this.CreatePrimedCounter("Memory", "Available MBytes");
8885
this.cpuCoreCounters = new List<PerformanceCounter>();
89-
90-
this.InitializeCpuCoreCounters();
9186
}
9287

9388
public async Task<SystemPerformanceMetrics> GetSystemMetricsAsync(bool lightweight = false)
@@ -146,6 +141,7 @@ public async Task<List<CpuCoreUsage>> GetCpuCoreUsageAsync()
146141

147142
try
148143
{
144+
this.EnsureCpuCoreCountersInitialized();
149145
var topology = await this.cpuTopologyService.DetectTopologyAsync().ConfigureAwait(false);
150146

151147
for (int i = 0; i < this.cpuCoreCounters.Count; i++)
@@ -178,6 +174,7 @@ public async Task<MemoryUsageInfo> GetMemoryUsageAsync()
178174
{
179175
try
180176
{
177+
this.EnsureSystemCountersInitialized();
181178
var memoryInfo = new MemoryUsageInfo();
182179

183180
// Get physical memory info
@@ -189,7 +186,7 @@ public async Task<MemoryUsageInfo> GetMemoryUsageAsync()
189186
}
190187

191188
// Get available memory
192-
memoryInfo.AvailablePhysicalMemory = (long)this.memoryCounter.NextValue() * 1024 * 1024; // Convert MB to bytes
189+
memoryInfo.AvailablePhysicalMemory = (long)(this.memoryCounter?.NextValue() ?? 0) * 1024 * 1024; // Convert MB to bytes
193190
memoryInfo.UsedPhysicalMemory = memoryInfo.TotalPhysicalMemory - memoryInfo.AvailablePhysicalMemory;
194191
memoryInfo.PhysicalMemoryUsagePercentage = memoryInfo.TotalPhysicalMemory > 0
195192
? ((double)memoryInfo.UsedPhysicalMemory / memoryInfo.TotalPhysicalMemory) * 100
@@ -376,6 +373,58 @@ private void InitializeCpuCoreCounters()
376373
}
377374
}
378375

376+
private void EnsureSystemCountersInitialized()
377+
{
378+
if (this.totalCpuCounter != null && this.memoryCounter != null)
379+
{
380+
return;
381+
}
382+
383+
lock (this.counterInitializationLock)
384+
{
385+
if (this.totalCpuCounter != null && this.memoryCounter != null)
386+
{
387+
return;
388+
}
389+
390+
PerformanceCounter? totalCpu = null;
391+
PerformanceCounter? memory = null;
392+
393+
try
394+
{
395+
totalCpu = this.CreatePrimedCounter("Processor", "% Processor Time", "_Total");
396+
memory = this.CreatePrimedCounter("Memory", "Available MBytes");
397+
398+
this.totalCpuCounter = totalCpu;
399+
this.memoryCounter = memory;
400+
}
401+
catch
402+
{
403+
totalCpu?.Dispose();
404+
memory?.Dispose();
405+
throw;
406+
}
407+
}
408+
}
409+
410+
private void EnsureCpuCoreCountersInitialized()
411+
{
412+
if (this.cpuCoreCounters.Count > 0)
413+
{
414+
return;
415+
}
416+
417+
lock (this.counterInitializationLock)
418+
{
419+
if (this.cpuCoreCounters.Count > 0)
420+
{
421+
return;
422+
}
423+
424+
this.InitializeCpuCoreCounters();
425+
}
426+
}
427+
379428
private PerformanceCounter CreatePrimedCounter(string categoryName, string counterName, string? instanceName = null)
380429
{
381430
try
@@ -403,7 +452,8 @@ private async Task<double> GetTotalCpuUsageAsync()
403452
{
404453
try
405454
{
406-
return this.totalCpuCounter.NextValue();
455+
this.EnsureSystemCountersInitialized();
456+
return this.totalCpuCounter?.NextValue() ?? 0;
407457
}
408458
catch (Exception ex)
409459
{
@@ -416,7 +466,8 @@ private async Task<long> GetAvailableMemoryAsync()
416466
{
417467
try
418468
{
419-
return (long)this.memoryCounter.NextValue() * 1024 * 1024; // Convert MB to bytes
469+
this.EnsureSystemCountersInitialized();
470+
return (long)(this.memoryCounter?.NextValue() ?? 0) * 1024 * 1024; // Convert MB to bytes
420471
}
421472
catch (Exception ex)
422473
{

Services/ServiceConfiguration.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,9 @@ private static IServiceCollection ConfigureProcessManagementServices(this IServi
147147

148148
// Performance monitoring services
149149
services.AddSingleton<IPerformanceMonitoringService, PerformanceMonitoringService>();
150+
services.AddSingleton(sp => new Lazy<IPerformanceMonitoringService>(
151+
() => sp.GetRequiredService<IPerformanceMonitoringService>()));
152+
services.AddSingleton<ISystemTrayStatusUpdater, SystemTrayStatusUpdater>();
150153

151154
return services;
152155
}
@@ -202,6 +205,9 @@ private static IServiceCollection ConfigurePresentationLayer(this IServiceCollec
202205
services.AddTransient<SettingsViewModel>();
203206
services.AddTransient<MainWindowViewModel>();
204207
services.AddTransient<PerformanceViewModel>();
208+
services.AddTransient(sp => new Lazy<PerformanceViewModel>(
209+
() => sp.GetRequiredService<PerformanceViewModel>()));
210+
services.AddTransient<IDiagnosticsViewModelProvider, DiagnosticsViewModelProvider>();
205211
services.AddTransient<LogViewerViewModel>();
206212
services.AddTransient<SystemTweaksViewModel>();
207213

0 commit comments

Comments
 (0)