diff --git a/src/Tgstation.Server.Host/Components/Session/SessionController.cs b/src/Tgstation.Server.Host/Components/Session/SessionController.cs
index ac6d3dd6a3..3992acc6ef 100644
--- a/src/Tgstation.Server.Host/Components/Session/SessionController.cs
+++ b/src/Tgstation.Server.Host/Components/Session/SessionController.cs
@@ -519,6 +519,10 @@ namespace Tgstation.Server.Host.Components.Session
return process.CreateDump(outputFile, minidump, cancellationToken);
}
+ ///
+ public double MeasureProcessorTimeDelta()
+ => process.MeasureProcessorTimeDelta();
+
///
/// The for .
///
diff --git a/src/Tgstation.Server.Host/System/IProcessBase.cs b/src/Tgstation.Server.Host/System/IProcessBase.cs
index b95b0bf928..64d11da92d 100644
--- a/src/Tgstation.Server.Host/System/IProcessBase.cs
+++ b/src/Tgstation.Server.Host/System/IProcessBase.cs
@@ -24,6 +24,12 @@ namespace Tgstation.Server.Host.System
///
long? MemoryUsage { get; }
+ ///
+ /// Gets the estimated CPU usage fraction of the process based on the last time this was called.
+ ///
+ /// The CPU's estimated usage as a value between 0 and 1.
+ double MeasureProcessorTimeDelta();
+
///
/// Set's the owned to a non-normal value.
///
diff --git a/src/Tgstation.Server.Host/System/Process.cs b/src/Tgstation.Server.Host/System/Process.cs
index f8da0a396b..09ad4aa3af 100644
--- a/src/Tgstation.Server.Host/System/Process.cs
+++ b/src/Tgstation.Server.Host/System/Process.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
@@ -87,6 +87,26 @@ namespace Tgstation.Server.Host.System
///
readonly Task? readTask;
+ ///
+ /// object for measuring processor time usage.
+ ///
+ readonly object processTimeMeasureLock;
+
+ ///
+ /// The last time was called.
+ ///
+ DateTimeOffset lastProcessorMeasureTime;
+
+ ///
+ /// The last value of .
+ ///
+ TimeSpan lastProcessorUsageTime;
+
+ ///
+ /// The last valid return value of .
+ ///
+ double lastProcessorUsageEstimation;
+
///
/// If the was disposed.
///
@@ -123,6 +143,8 @@ namespace Tgstation.Server.Host.System
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
+ processTimeMeasureLock = new object();
+
Lifetime = WrapLifetimeTask();
if (preExisting)
@@ -147,6 +169,8 @@ namespace Tgstation.Server.Host.System
DefaultIOManager.BlockingTaskCreationOptions,
TaskScheduler.Current);
+ MeasureProcessorTimeDelta();
+
logger.LogTrace("Created process ID: {pid}", Id);
}
@@ -267,6 +291,34 @@ namespace Tgstation.Server.Host.System
return processFeatures.CreateDump(handle, outputFile, minidump, cancellationToken);
}
+ ///
+ public double MeasureProcessorTimeDelta()
+ {
+ lock (processTimeMeasureLock)
+ {
+ try
+ {
+ var now = DateTimeOffset.UtcNow;
+ var newTime = handle.TotalProcessorTime;
+
+ var timeDelta = now - lastProcessorMeasureTime;
+ var newUsage = newTime - lastProcessorUsageTime;
+
+ lastProcessorMeasureTime = now;
+ lastProcessorUsageTime = newTime;
+
+ if (timeDelta != TimeSpan.Zero)
+ lastProcessorUsageEstimation = newUsage / (Environment.ProcessorCount * timeDelta);
+ }
+ catch (Exception ex)
+ {
+ logger.LogWarning(ex, "Error measuring processor time delta!");
+ }
+
+ return lastProcessorUsageEstimation;
+ }
+ }
+
///
/// Attaches a log message to the process' exit event.
///