Skip to content

Commit

Permalink
Fix CPU statistics (Process/Total)
Browse files Browse the repository at this point in the history
Revert Windows to PerformanceCounter metrics
Change calculation for Linux CPU usage
  • Loading branch information
NetDwarf committed Jul 13, 2022
1 parent 9b22885 commit 913ed8f
Show file tree
Hide file tree
Showing 8 changed files with 155 additions and 83 deletions.
24 changes: 0 additions & 24 deletions GameServer/PerformanceStatistics/CpuUsageStatistics.cs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
using System;
using System.Collections;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;

namespace DOL.PerformanceStatistics
{
public class CurrentProcessCpuUsagePercentStatistic : IPerformanceStatistic
{
private IPerformanceStatistic processorTimeRatioStatistic;

public CurrentProcessCpuUsagePercentStatistic()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
processorTimeRatioStatistic = new PerformanceCounterStatistic("Process", "% processor time", Process.GetCurrentProcess().ProcessName);
}
else
{
processorTimeRatioStatistic = new LinuxCurrentProcessUsagePercentStatistic();
}
}

public float GetNextValue()
=> processorTimeRatioStatistic.GetNextValue();
}

#if NET
[UnsupportedOSPlatform("Windows")]
#endif
internal class LinuxCurrentProcessUsagePercentStatistic : IPerformanceStatistic
{
private IPerformanceStatistic idleProcessorTimeStatistic = new PerSecondStatistic(new LinuxSystemIdleProcessorTimeInSeconds());
private IPerformanceStatistic totalProcessorTimeStatistic = new PerSecondStatistic(new LinuxTotalProcessorTimeInSeconds());
private IPerformanceStatistic currentProcessProcessorTimeStatistic = new PerSecondStatistic(new LinuxCurrentProcessProcessorTimeInSeconds());

public float GetNextValue()
{
var idleTime = idleProcessorTimeStatistic.GetNextValue();
var totalTime = totalProcessorTimeStatistic.GetNextValue();
var processTime = currentProcessProcessorTimeStatistic.GetNextValue();
return processTime / totalTime * 100 * Environment.ProcessorCount;
}
}

#if NET
[UnsupportedOSPlatform("Windows")]
#endif
internal class LinuxCurrentProcessProcessorTimeInSeconds : IPerformanceStatistic
{
public float GetNextValue()
{
var pid = Process.GetCurrentProcess().Id;
var statArray = File.ReadAllText($"/proc/{pid}/stat").Split(' ');
var processorTime = Convert.ToInt64(statArray[13]) + Convert.ToInt64(statArray[14]);
return processorTime * 0.001f;
}
}
}
37 changes: 8 additions & 29 deletions GameServer/PerformanceStatistics/DiskTransferStatistics.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
Expand All @@ -12,42 +11,22 @@ public class DiskTransfersPerSecondStatistic : IPerformanceStatistic

public DiskTransfersPerSecondStatistic()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) performanceStatistic = new WindowsDiskTransfersPerSecondStatistic();
else performanceStatistic = new LinuxDiskTransfersPerSecondStatistic();
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
performanceStatistic = new PerformanceCounterStatistic("PhysicalDisk", "Disk Transfers/sec", "_Total");
}
else
{
performanceStatistic = new PerSecondStatistic(new LinuxTotalDiskTransfers());
}
}

public float GetNextValue() => performanceStatistic.GetNextValue();
}

#if NET
[SupportedOSPlatform("Windows")]
#endif
internal class WindowsDiskTransfersPerSecondStatistic : IPerformanceStatistic
{
PerformanceCounter performanceCounter;
public WindowsDiskTransfersPerSecondStatistic()
{
performanceCounter = new PerformanceCounter("PhysicalDisk", "Disk Transfers/sec", "_Total");
}

public float GetNextValue() => performanceCounter.NextValue();
}

#if NET
[UnsupportedOSPlatform("Windows")]
#endif
internal class LinuxDiskTransfersPerSecondStatistic : IPerformanceStatistic
{
private IPerformanceStatistic diskTransfersPerSecondStatistic;

public LinuxDiskTransfersPerSecondStatistic()
{
diskTransfersPerSecondStatistic = new PerSecondStatistic(new LinuxTotalDiskTransfers());
}

public float GetNextValue() => diskTransfersPerSecondStatistic.GetNextValue();
}

internal class LinuxTotalDiskTransfers : IPerformanceStatistic
{
public float GetNextValue()
Expand Down
29 changes: 8 additions & 21 deletions GameServer/PerformanceStatistics/PageFaultStatistics.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
Expand All @@ -13,31 +12,19 @@ public class PageFaultsPerSecondStatistic : IPerformanceStatistic

public PageFaultsPerSecondStatistic()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) performanceStatistic = new WindowsPageFaultsPerSecondStatistic();
else performanceStatistic = new LinuxPageFaultsPerSecondStatistic();
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
performanceStatistic = new PerformanceCounterStatistic("Memory", "Pages/sec", null);
}
else
{
performanceStatistic = new LinuxPageFaultsPerSecondStatistic();
}
}

public float GetNextValue() => performanceStatistic.GetNextValue();
}

#if NET
[SupportedOSPlatform("Windows")]
#endif
internal class WindowsPageFaultsPerSecondStatistic : IPerformanceStatistic
{
PerformanceCounter performanceCounter;

public WindowsPageFaultsPerSecondStatistic()
{
performanceCounter = new PerformanceCounter("Memory", "Pages/sec", null);
}

public float GetNextValue()
{
return performanceCounter.NextValue();
}
}

#if NET
[UnsupportedOSPlatform("Windows")]
#endif
Expand Down
21 changes: 21 additions & 0 deletions GameServer/PerformanceStatistics/PerformaceCounterStatistics.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System.Diagnostics;
using System.Runtime.Versioning;

namespace DOL.PerformanceStatistics
{
#if NET
[SupportedOSPlatform("Windows")]
#endif
public class PerformanceCounterStatistic : IPerformanceStatistic
{
private PerformanceCounter performanceCounter;

public PerformanceCounterStatistic(string categoryName, string counterName, string instanceName)
{
performanceCounter = new PerformanceCounter(categoryName, counterName, instanceName);
performanceCounter.NextValue();
}

public float GetNextValue() => performanceCounter.NextValue();
}
}
62 changes: 55 additions & 7 deletions GameServer/PerformanceStatistics/SystemCpuUsageStatistics.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;

namespace DOL.PerformanceStatistics
{
Expand All @@ -10,20 +12,66 @@ public class SystemCpuUsagePercent : IPerformanceStatistic

public SystemCpuUsagePercent()
{
processorTimeRatioStatistic = new PerSecondStatistic(new TotalSystemProcessorTimeInSeconds());
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
processorTimeRatioStatistic = new PerformanceCounterStatistic("Processor", "% processor time", "_total");
}
else
{
processorTimeRatioStatistic = new LinuxSystemCpuUsagePercent();
}
}

public float GetNextValue()
=> processorTimeRatioStatistic.GetNextValue() / Environment.ProcessorCount * 100;
=> processorTimeRatioStatistic.GetNextValue();
}

internal class TotalSystemProcessorTimeInSeconds : IPerformanceStatistic
#if NET
[UnsupportedOSPlatform("Windows")]
#endif
internal class LinuxSystemCpuUsagePercent : IPerformanceStatistic
{
private IPerformanceStatistic processorTimeStatistic;
private IPerformanceStatistic idleTimeStatistic;

public LinuxSystemCpuUsagePercent()
{
processorTimeStatistic = new PerSecondStatistic(new LinuxTotalProcessorTimeInSeconds());
idleTimeStatistic = new PerSecondStatistic(new LinuxSystemIdleProcessorTimeInSeconds());
}

public float GetNextValue()
{
var cpuUsage = (1 - (idleTimeStatistic.GetNextValue() / processorTimeStatistic.GetNextValue()));
return cpuUsage * 100;
}
}

#if NET
[UnsupportedOSPlatform("Windows")]
#endif
internal class LinuxTotalProcessorTimeInSeconds : IPerformanceStatistic
{
public float GetNextValue()
{
var cpuTimeInSeconds = File.ReadAllText("/proc/stat").Split('\n')
.First().Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
.Skip(1).Select(c => Convert.ToInt64(c)).Aggregate(0L, (a, b) => a + b) * 0.001f;
return cpuTimeInSeconds;
}
}

#if NET
[UnsupportedOSPlatform("Windows")]
#endif
internal class LinuxSystemIdleProcessorTimeInSeconds : IPerformanceStatistic
{
public float GetNextValue()
{
return (float)Process.GetProcesses()
.Select(p => p.TotalProcessorTime)
.Aggregate(TimeSpan.Zero, (p1, p2) => p1 + p2).TotalSeconds;
var cpuIdleTimeString = File.ReadAllText("/proc/stat").Split('\n')
.First().Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)[4];
var cpuIdleTimeInSeconds = Convert.ToInt64(cpuIdleTimeString) * 0.001f;
return cpuIdleTimeInSeconds;
}
}
}
2 changes: 1 addition & 1 deletion GameServer/gameutils/StatPrint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public static void OnScriptCompiled(DOLEvent e, object sender, EventArgs args)
m_timerStatsByMgr = new Hashtable();
m_timer = new Timer(new TimerCallback(PrintStats), null, 10000, 0);
systemCpuUsagePercent = TryToCreateStatistic(() => new SystemCpuUsagePercent());
programCpuUsagePercent = TryToCreateStatistic(() => new ProgramCpuUsagePercentStatistic());
programCpuUsagePercent = TryToCreateStatistic(() => new CurrentProcessCpuUsagePercentStatistic());
diskTransfersPerSecond = TryToCreateStatistic(() => new DiskTransfersPerSecondStatistic());
pageFaultsPerSecond = TryToCreateStatistic(() => new PageFaultsPerSecondStatistic());
}
Expand Down
2 changes: 1 addition & 1 deletion GameServer/gameutils/StatSave.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public static void OnScriptCompiled(DOLEvent e, object sender, EventArgs args)
m_timer = new Timer(new TimerCallback(SaveStats), null, INITIAL_DELAY, Timeout.Infinite);
}

programCpuUsagePercent = new ProgramCpuUsagePercentStatistic();
programCpuUsagePercent = new CurrentProcessCpuUsagePercentStatistic();
}

[ScriptUnloadedEvent]
Expand Down

0 comments on commit 913ed8f

Please sign in to comment.