diff --git a/GameServer/PerformanceStatistics/CpuUsageStatistics.cs b/GameServer/PerformanceStatistics/CpuUsageStatistics.cs deleted file mode 100644 index 1e93fedfe1..0000000000 --- a/GameServer/PerformanceStatistics/CpuUsageStatistics.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Diagnostics; - -namespace DOL.PerformanceStatistics -{ - public class ProgramCpuUsagePercentStatistic : IPerformanceStatistic - { - private IPerformanceStatistic processorTimeRatioStatistic; - - public ProgramCpuUsagePercentStatistic() - { - processorTimeRatioStatistic = new PerSecondStatistic(new TotalProgramProcessorTimeInSeconds()); - } - - public float GetNextValue() - => processorTimeRatioStatistic.GetNextValue() / Environment.ProcessorCount * 100; - } - - internal class TotalProgramProcessorTimeInSeconds : IPerformanceStatistic - { - public float GetNextValue() - => (float)Process.GetCurrentProcess().TotalProcessorTime.TotalSeconds; - } -} \ No newline at end of file diff --git a/GameServer/PerformanceStatistics/CurrentProcessCpuUsageStatistics.cs b/GameServer/PerformanceStatistics/CurrentProcessCpuUsageStatistics.cs new file mode 100644 index 0000000000..ee28a962f2 --- /dev/null +++ b/GameServer/PerformanceStatistics/CurrentProcessCpuUsageStatistics.cs @@ -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; + } + } +} \ No newline at end of file diff --git a/GameServer/PerformanceStatistics/DiskTransferStatistics.cs b/GameServer/PerformanceStatistics/DiskTransferStatistics.cs index 19535fb597..1e29f02630 100644 --- a/GameServer/PerformanceStatistics/DiskTransferStatistics.cs +++ b/GameServer/PerformanceStatistics/DiskTransferStatistics.cs @@ -1,5 +1,4 @@ using System; -using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; using System.Runtime.Versioning; @@ -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() diff --git a/GameServer/PerformanceStatistics/PageFaultStatistics.cs b/GameServer/PerformanceStatistics/PageFaultStatistics.cs index 583dea2734..7e4f67cf84 100644 --- a/GameServer/PerformanceStatistics/PageFaultStatistics.cs +++ b/GameServer/PerformanceStatistics/PageFaultStatistics.cs @@ -1,5 +1,4 @@ using System; -using System.Diagnostics; using System.IO; using System.Linq; using System.Runtime.InteropServices; @@ -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 diff --git a/GameServer/PerformanceStatistics/PerformaceCounterStatistics.cs b/GameServer/PerformanceStatistics/PerformaceCounterStatistics.cs new file mode 100644 index 0000000000..e702b543b0 --- /dev/null +++ b/GameServer/PerformanceStatistics/PerformaceCounterStatistics.cs @@ -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(); + } +} \ No newline at end of file diff --git a/GameServer/PerformanceStatistics/SystemCpuUsageStatistics.cs b/GameServer/PerformanceStatistics/SystemCpuUsageStatistics.cs index a55373fb66..d14a967c80 100644 --- a/GameServer/PerformanceStatistics/SystemCpuUsageStatistics.cs +++ b/GameServer/PerformanceStatistics/SystemCpuUsageStatistics.cs @@ -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 { @@ -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; } } } \ No newline at end of file diff --git a/GameServer/gameutils/StatPrint.cs b/GameServer/gameutils/StatPrint.cs index 7bcc40c120..5e9b3890be 100644 --- a/GameServer/gameutils/StatPrint.cs +++ b/GameServer/gameutils/StatPrint.cs @@ -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()); } diff --git a/GameServer/gameutils/StatSave.cs b/GameServer/gameutils/StatSave.cs index 5db5cf659e..5df9e7f8d8 100644 --- a/GameServer/gameutils/StatSave.cs +++ b/GameServer/gameutils/StatSave.cs @@ -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]