Browse Source

Added periodic performance metrics collection

CPKreuz 8 months ago
parent
commit
77910434ad

+ 1 - 0
src/PixiEditor/Models/AnalyticsAPI/AnalyticEventTypes.cs

@@ -13,6 +13,7 @@ public class AnalyticEventTypes
     public static string SwitchTool { get; } = GetEventType("SwitchTool");
     public static string UseTool { get; } = GetEventType("UseTool");
     public static string ResumeSession { get; } = GetEventType("ResumeSession");
+    public static string PeriodicPerformanceReport { get; } = GetEventType("PeriodicPerformanceReport");
 
     private static string GetEventType(string value) => $"PixiEditor.{value}";
 }

+ 2 - 1
src/PixiEditor/Models/AnalyticsAPI/Analytics.cs

@@ -1,4 +1,5 @@
-using System.Reflection;
+using System.Diagnostics;
+using System.Reflection;
 using PixiEditor.ChangeableDocument.Changeables.Graph;
 using PixiEditor.Models.Commands.CommandContext;
 using PixiEditor.Models.Files;

+ 3 - 0
src/PixiEditor/Models/AnalyticsAPI/AnalyticsPeriodicReporter.cs

@@ -9,6 +9,7 @@ public class AnalyticsPeriodicReporter
     
     private readonly SemaphoreSlim _semaphore = new(1, 1);
     private readonly AnalyticsClient _client;
+    private readonly PeriodicPerformanceReporter _performanceReporter;
     
     private readonly List<AnalyticEvent> _backlog = new();
     private readonly CancellationTokenSource _cancellationToken = new();
@@ -27,6 +28,7 @@ public class AnalyticsPeriodicReporter
         Instance = this;
         
         _client = client;
+        _performanceReporter = new PeriodicPerformanceReporter(this);
     }
 
     public void Start(Guid? sessionId)
@@ -40,6 +42,7 @@ public class AnalyticsPeriodicReporter
         }
 
         Task.Run(RunAsync);
+        _performanceReporter.StartPeriodicReporting();
     }
 
     public async Task StopAsync()

+ 74 - 0
src/PixiEditor/Models/AnalyticsAPI/PeriodicPerformanceReporter.cs

@@ -0,0 +1,74 @@
+using System.Diagnostics;
+using Timer = System.Timers.Timer;
+
+namespace PixiEditor.Models.AnalyticsAPI;
+
+public class PeriodicPerformanceReporter(AnalyticsPeriodicReporter analyticsReporter)
+{
+    private long _lastTotalAllocatedBytes;
+    private TimeSpan _lastTotalGcPauseTime;
+
+    public void StartPeriodicReporting()
+    {
+        var timer = new Timer
+        {
+            Interval = TimeSpan.FromSeconds(45).TotalMilliseconds,
+            AutoReset = true
+        };
+
+        timer.Elapsed += (_, _) => Task.Run(CollectPerformanceMetricAsync);
+        
+        timer.Start();
+    }
+    
+    private async Task CollectPerformanceMetricAsync()
+    {
+        var process = Process.GetCurrentProcess();
+        
+        var data = new Dictionary<string, object>();
+
+        var collectionStartTime = DateTime.Now;
+        
+        var processorTime = await SampleProcessorTimeAsync(process);
+        data["UserTime"] = processorTime.userTime;
+        data["PrivilegedTime"] = processorTime.privilegedTime;
+        
+        data["PrivateMemorySize"] = process.PrivateMemorySize64;
+        data["WorkingSet"] = process.WorkingSet64;
+
+        var currentTotalGcPauseTime = GC.GetTotalPauseDuration();
+        data["GcPauseTime"] = _lastTotalGcPauseTime;
+        _lastTotalGcPauseTime = currentTotalGcPauseTime;
+
+        var handles = process.HandleCount;
+        var threads = process.Threads.Count;
+        
+        data["Handles"] = handles;
+        data["Threads"] = threads;
+        
+        data["CollectionTime"] = DateTime.Now - collectionStartTime;
+        
+        var e = new AnalyticEvent
+        {
+            EventType = AnalyticEventTypes.PeriodicPerformanceReport,
+            Time = DateTime.UtcNow,
+            Data = data
+        };
+        
+        analyticsReporter.AddEvent(e);
+    }
+
+    private async Task<(TimeSpan userTime, TimeSpan privilegedTime)> SampleProcessorTimeAsync(Process process)
+    {
+        var userStartTime = process.UserProcessorTime;
+        var privilegedStartTime = process.PrivilegedProcessorTime;
+
+        await Task.Delay(TimeSpan.FromSeconds(10));
+        
+        process.Refresh();
+        var userTime = process.UserProcessorTime - userStartTime;
+        var privilegedTime = process.PrivilegedProcessorTime - privilegedStartTime;
+        
+        return (userTime, privilegedTime);
+    }
+}