Skip to content

Commit

Permalink
ETW Native Library and RateCalculation fixes.
Browse files Browse the repository at this point in the history
  • Loading branch information
creizlein committed Jul 23, 2023
1 parent c270984 commit 0c1496a
Show file tree
Hide file tree
Showing 11 changed files with 193 additions and 51 deletions.
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ global.json
smk-*.bat
frm*.resx
tab*.resx
TODO.md

# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
Expand Down Expand Up @@ -366,4 +365,4 @@ MigrationBackup/
.ionide/

# Fody - auto-generated XML schema
FodyWeavers.xsd
FodyWeavers.xsd
4 changes: 2 additions & 2 deletions make-release.bat
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
@echo off
dotnet publish --nologo -c Release /p:PublishProfileFullPath=%cd%\src\Properties\Release.pubxml
tar -a -cf %cd%\bin\Publish\sMkTaskManager.zip -C %cd%\bin\Publish *.exe
dotnet publish --nologo -c Release /p:PublishProfileFullPath="%cd%\src\Properties\Release.pubxml"
tar -a -cf "%cd%\bin\Publish\sMkTaskManager.zip" -C "%cd%\bin\Publish" *.exe
27 changes: 14 additions & 13 deletions src/Classes/Shared.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@
using System.Runtime.Versioning;
using System.Runtime.CompilerServices;
using System.Globalization;

using sMkTaskManager.Classes;
namespace sMkTaskManager;

[SupportedOSPlatform("windows")]
internal static partial class Shared {
private static string _SystemAccount = "";

internal static int bpi = 20; // Base PID Ignore
internal static List<string> skipProcess = new(new[] { "audiodg" });
internal static List<string> skipServices = new();
internal static string TotalProcessorsBin = "".PadLeft(Environment.ProcessorCount, '1');
internal static string DebuggerCmd = "";
public static int bpi = 20; // Base PID Ignore
public static List<string> skipProcess = new(new[] { "audiodg" });
public static List<string> skipServices = new();
public static string TotalProcessorsBin = "".PadLeft(Environment.ProcessorCount, '1');
public static string DebuggerCmd = "";
public static TaskManagetETW ETW = new();

public static bool IsNumeric(string value) => double.TryParse(value, out _);
public static bool IsNumeric(this object value) => double.TryParse(Convert.ToString(value), out _);
Expand All @@ -35,15 +36,15 @@ public static string TimeDiff(long startTime, short Format = 1) {
};
}

internal static void NotImplemented([CallerMemberName] string feature = "") {
public static void NotImplemented([CallerMemberName] string feature = "") {
MessageBox.Show("This feature is not implemented yet.", feature, MessageBoxButtons.OK, MessageBoxIcon.Information);
}
internal static void DebugTrap(Exception e, int Code = 0, [CallerMemberName] string Method = "") {
public static void DebugTrap(Exception e, int Code = 0, [CallerMemberName] string Method = "") {
Debug.WriteLine($"*** Error at `{Method}` - Code: {Code} - Threw: {e.Message}");
Debug.WriteLine(e.ToString());
}

internal static string GetSystemAccount() {
public static string GetSystemAccount() {
if (_SystemAccount != "") return _SystemAccount;
try {
System.Security.Principal.SecurityIdentifier sid = new(System.Security.Principal.WellKnownSidType.LocalSystemSid, null);
Expand All @@ -56,7 +57,7 @@ internal static string GetSystemAccount() {
}
return _SystemAccount!;
}
internal static void GetDebuggerCmd() {
public static void GetDebuggerCmd() {
string SubKey = "Software\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug";
string _Debugger = "";
Microsoft.Win32.RegistryKey ParentKey = Microsoft.Win32.Registry.LocalMachine;
Expand Down Expand Up @@ -121,18 +122,18 @@ public static bool AddPrivilege(string privilege) {
} else { return false; }
} else { return false; }
}

}

internal class CpuUsage {
private Classes.API.FILETIME _idleTime, _kernTime, _userTime;
private API.FILETIME _idleTime, _kernTime, _userTime;
private long _oldCpuUsage = 0, _oldKernUsage = 0, _oldUserUsage = 0;
private double _rawIdleTime, _rawKernTime, _rawUserTime;
private int _CpuUsage, _UserUsage, _KernelUsage;
private long _now;
private readonly int Processors = Environment.ProcessorCount;

public void Refresh(long sinceWhen) {
Classes.API.GetSystemTimes(ref _idleTime, ref _kernTime, ref _userTime);
API.GetSystemTimes(ref _idleTime, ref _kernTime, ref _userTime);
_now = DateTime.Now.Ticks;

if (_oldCpuUsage == 0) {
Expand Down
8 changes: 4 additions & 4 deletions src/Classes/TaskManagerConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,10 @@ public void Update(in TaskManagerConnection sourceConnection) {

LifeTime = Shared.TimeDiff(CreationTime, 1);

SentDeltaValue = ETW.NetStats(Ident[2..]).Sent - SentValue;
ReceivedDeltaValue = ETW.NetStats(Ident[2..]).Received - ReceivedValue;
SentValue = ETW.NetStats(Ident[2..]).Sent;
ReceivedValue = ETW.NetStats(Ident[2..]).Received;
SentDeltaValue = Shared.ETW.NetStats(Ident[2..]).Sent - SentValue;
ReceivedDeltaValue = Shared.ETW.NetStats(Ident[2..]).Received - ReceivedValue;
SentValue = Shared.ETW.NetStats(Ident[2..]).Sent;
ReceivedValue = Shared.ETW.NetStats(Ident[2..]).Received;
SentRateValue = CalculateRateValue(SentDeltaValue);
ReceivedRateValue = CalculateRateValue(ReceivedDeltaValue);

Expand Down
142 changes: 142 additions & 0 deletions src/Classes/TaskManagerEtwNative.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
using System.Diagnostics;
using Microsoft.Diagnostics.Tracing.Parsers;
using Microsoft.Diagnostics.Tracing.Parsers.Kernel;
using Microsoft.Diagnostics.Tracing.Session;
namespace sMkTaskManager.Classes;

internal class TaskManagetETW {
private Thread? etwThread;
private TraceEventSession? kernelSession;
private readonly Dictionary<int, EtwStats> _AllStats = new() { { 0, new() } };
private readonly Dictionary<int, EtwDiskStats> _DiskStats = new();
private readonly Dictionary<string, EtwNetStats> _NetStats = new();

public string sessionName = "sMkTaskManager";
public System.Threading.ThreadState? State => etwThread?.ThreadState;
public bool Running => etwThread?.ThreadState == (System.Threading.ThreadState.Running | System.Threading.ThreadState.Background);
public static bool IsElevated => TraceEventSession.IsElevated() ?? false;

public EtwStats Stats(int PID) => _AllStats.ContainsKey(PID) ? _AllStats[PID] : new EtwStats();
public EtwStats Stats(uint PID) => _AllStats.ContainsKey((int)PID) ? _AllStats[(int)PID] : new EtwStats();
public EtwNetStats NetStats(string Hash) => _NetStats.ContainsKey(Hash) ? _NetStats[Hash] : new EtwNetStats();
public EtwDiskStats DiskStats(int DiskNumber) => _DiskStats.ContainsKey(DiskNumber) ? _DiskStats[DiskNumber] : new EtwDiskStats();

public bool Start() {
if (!Running && IsElevated) {
StartMonitor();
Debug.WriteLine("ETW has been Started");
}
return Running;
}
public bool Stop() {
if (etwThread != null) {
StopSession();
Debug.WriteLine("ETW Disposed");
}
return !Running;
}
public void Flush() {
kernelSession?.Flush();
}

private void StartMonitor() {
etwThread = new Thread(StartSession) {
Name = "sMkETW",
IsBackground = true,
Priority = ThreadPriority.Normal
};
etwThread.Start();
}
private void StartSession() {
kernelSession = new TraceEventSession(sessionName);
kernelSession.EnableKernelProvider(
KernelTraceEventParser.Keywords.DiskIO |
KernelTraceEventParser.Keywords.NetworkTCPIP
);

kernelSession.Source.Kernel.DiskIORead += OnDiskRead;
kernelSession.Source.Kernel.DiskIOWrite += OnDiskWrite;

kernelSession.Source.Kernel.TcpIpRecv += OnTcpIpRecv;
kernelSession.Source.Kernel.TcpIpRecvIPV6 += OnTcpIpRecvIPV6;
kernelSession.Source.Kernel.UdpIpRecv += OnUdpIpRecv;
kernelSession.Source.Kernel.UdpIpRecvIPV6 += OnUdpIpRecvIPV6;

kernelSession.Source.Kernel.TcpIpSend += OnTcpIpSend;
kernelSession.Source.Kernel.TcpIpSendIPV6 += OnTcpIpSendIPV6;
kernelSession.Source.Kernel.UdpIpSend += OnUdpIpSend;
kernelSession.Source.Kernel.UdpIpSendIPV6 += OnUdpIpSendIPV6;

kernelSession.Source.Process();
}
private void StopSession() {
kernelSession?.Dispose();
}

private void OnDiskRead(DiskIOTraceData obj) {
_AllStats[0].DiskReaded += (uint)obj.TransferSize;
// Per Disk
if (!_DiskStats.ContainsKey(obj.DiskNumber)) _DiskStats.Add(obj.DiskNumber, new());
_DiskStats[obj.DiskNumber].Readed += (uint)obj.TransferSize;
// Per Process
if (obj.ProcessID > 0) {
if (!_AllStats.ContainsKey(obj.ProcessID)) _AllStats.Add(obj.ProcessID, new());
_AllStats[obj.ProcessID].DiskReaded += (uint)obj.TransferSize;
}
}
private void OnDiskWrite(DiskIOTraceData obj) {
_AllStats[0].DiskWroted += (uint)obj.TransferSize;
// Per Disk
if (!_DiskStats.ContainsKey(obj.DiskNumber)) _DiskStats.Add(obj.DiskNumber, new());
_DiskStats[obj.DiskNumber].Wroted += (uint)obj.TransferSize;
// Per Process
if (obj.ProcessID > 0) {
if (!_AllStats.ContainsKey(obj.ProcessID)) _AllStats.Add(obj.ProcessID, new());
_AllStats[obj.ProcessID].DiskWroted += (uint)obj.TransferSize;
}
}
private void OnTcpIpSend(TcpIpSendTraceData mof) { ProcessNetworkPacket(mof.ProcessID, mof.size, $"{mof.saddr}:{mof.sport}-{mof.daddr}:{mof.dport}", true); }
private void OnTcpIpSendIPV6(TcpIpV6SendTraceData mof) { ProcessNetworkPacket(mof.ProcessID, mof.size, $"{mof.saddr}:{mof.sport}-{mof.daddr}:{mof.dport}", true); }
private void OnTcpIpRecv(TcpIpTraceData mof) { ProcessNetworkPacket(mof.ProcessID, mof.size, $"{mof.saddr}:{mof.sport}-{mof.daddr}:{mof.dport}", false); }
private void OnTcpIpRecvIPV6(TcpIpV6TraceData mof) { ProcessNetworkPacket(mof.ProcessID, mof.size, $"{mof.saddr}:{mof.sport}-{mof.daddr}:{mof.dport}", false); }
private void OnUdpIpSend(UdpIpTraceData mof) { ProcessNetworkPacket(mof.ProcessID, mof.size, $"{mof.saddr}:{mof.sport}-{mof.daddr}:{mof.dport}", true); }
private void OnUdpIpSendIPV6(UpdIpV6TraceData mof) { ProcessNetworkPacket(mof.ProcessID, mof.size, $"{mof.saddr}:{mof.sport}-{mof.daddr}:{mof.dport}", true); }
private void OnUdpIpRecv(UdpIpTraceData mof) { ProcessNetworkPacket(mof.ProcessID, mof.size, $"{mof.saddr}:{mof.sport}-{mof.daddr}:{mof.dport}", false); }
private void OnUdpIpRecvIPV6(UpdIpV6TraceData mof) { ProcessNetworkPacket(mof.ProcessID, mof.size, $"{mof.saddr}:{mof.sport}-{mof.daddr}:{mof.dport}", false); }
private void ProcessNetworkPacket(in int ProcessID, in int Size, in string Hash, in bool isSent) {
if (Size <= 0) return;
/* Common for all Network Events, just prepare */
if (ProcessID > 0 && !_AllStats.ContainsKey(ProcessID)) _AllStats.Add(ProcessID, new EtwStats());
if (!_NetStats.ContainsKey(Hash)) _NetStats.Add(Hash, new EtwNetStats());

if (isSent) {
/* Compute to NetSent */
_AllStats[0].NetSent += (uint)Size;
if (ProcessID > 0) _AllStats[ProcessID].NetSent += (uint)Size;
_NetStats[Hash].Sent += (uint)Size;
} else {
/* Compute to NetReceived */
_AllStats[0].NetReceived += (uint)Size;
if (ProcessID > 0) _AllStats[ProcessID].NetReceived += (uint)Size;
_NetStats[Hash].Received += (uint)Size;

}

}

public class EtwStats {
public ulong DiskReaded = 0;
public ulong DiskWroted = 0;
public ulong NetSent = 0;
public ulong NetReceived = 0;
}
public class EtwDiskStats {
public ulong Readed = 0;
public ulong Wroted = 0;
}
public class EtwNetStats {
public ulong Sent = 0;
public ulong Received = 0;
}

}
24 changes: 12 additions & 12 deletions src/Classes/TaskManagerProcess.cs
Original file line number Diff line number Diff line change
Expand Up @@ -257,11 +257,11 @@ public void Update(API.SYSTEM_PROCESS_INFORMATION spi, in HashSet<string> vv, bo
if (vv.Contains("VirtualMemoryPeak")) VirtualMemoryPeakValue = spi.PeakVirtualSize;
// I/O Counters Values
if (vv.Contains("ReadTransfer") || vv.Contains("ReadTransferDelta")) {
ReadTransferDeltaValue = (ReadTransferValue == 0) ? 0 : spi.ReadTransferCount - ReadTransferValue;
ReadTransferDeltaValue = (ReadTransferValue == 0) ? 0 : spi.ReadTransferCount - ReadTransferValue;
ReadTransferValue = spi.ReadTransferCount;
}
if (vv.Contains("ReadOperations") || vv.Contains("ReadOperationsDelta")) {
ReadOperationsDeltaValue = (ReadOperationsValue == 0) ? 0 : spi.ReadOperationCount - ReadOperationsValue;
ReadOperationsDeltaValue = (ReadOperationsValue == 0) ? 0 : spi.ReadOperationCount - ReadOperationsValue;
ReadOperationsValue = spi.ReadOperationCount;
}
if (vv.Contains("WriteTransfer") || vv.Contains("WriteTransferDelta")) {
Expand All @@ -281,25 +281,25 @@ public void Update(API.SYSTEM_PROCESS_INFORMATION spi, in HashSet<string> vv, bo
OtherOperationsValue = spi.OtherOperationCount;
}
// ETW Data Values, if running
if (ETW.Running) {
if (Shared.ETW.Running) {
if (vv.Contains("DiskRead") || vv.Contains("DiskReadDelta") || vv.Contains("DiskReadRate")) {
DiskReadDeltaValue = (DiskReadValue == 0) ? 0 : ETW.Stats(_PID).DiskReaded - DiskReadValue;
DiskReadValue = ETW.Stats(_PID).DiskReaded;
DiskReadDeltaValue = (DiskReadValue == 0) ? 0 : Shared.ETW.Stats(_PID).DiskReaded - DiskReadValue;
DiskReadValue = Shared.ETW.Stats(_PID).DiskReaded;
DiskReadRateValue = CalculateRateValue(DiskReadDeltaValue);
}
if (vv.Contains("DiskWrite") || vv.Contains("DiskWriteDelta") || vv.Contains("DiskWriteRate")) {
DiskWriteDeltaValue = (DiskWriteValue == 0) ? 0 : ETW.Stats(_PID).DiskWroted - DiskWriteValue;
DiskWriteValue = ETW.Stats(_PID).DiskWroted;
DiskWriteDeltaValue = (DiskWriteValue == 0) ? 0 : Shared.ETW.Stats(_PID).DiskWroted - DiskWriteValue;
DiskWriteValue = Shared.ETW.Stats(_PID).DiskWroted;
DiskWriteRateValue = CalculateRateValue(DiskWriteDeltaValue);
}
if (vv.Contains("NetSent") || vv.Contains("NetSentDelta") || vv.Contains("NetSentRate")) {
NetSentDeltaValue = (NetSentValue == 0) ? 0 : ETW.Stats(_PID).NetSent - NetSentValue;
NetSentValue = ETW.Stats(_PID).NetSent;
NetSentDeltaValue = (NetSentValue == 0) ? 0 : Shared.ETW.Stats(_PID).NetSent - NetSentValue;
NetSentValue = Shared.ETW.Stats(_PID).NetSent;
NetSentRateValue = CalculateRateValue(NetSentDeltaValue);
}
if (vv.Contains("NetReceived") || vv.Contains("NetReceivedDelta") || vv.Contains("NetReceivedRate")) {
NetRcvdDeltaValue = (NetRcvdValue == 0) ? 0 : ETW.Stats(_PID).NetReceived - NetRcvdValue;
NetRcvdValue = ETW.Stats(_PID).NetReceived;
NetRcvdDeltaValue = (NetRcvdValue == 0) ? 0 : Shared.ETW.Stats(_PID).NetReceived - NetRcvdValue;
NetRcvdValue = Shared.ETW.Stats(_PID).NetReceived;
NetRcvdRateValue = CalculateRateValue(NetRcvdDeltaValue);
}
}
Expand Down Expand Up @@ -492,7 +492,7 @@ private static bool imSuspended(in API.SYSTEM_EXTENDED_THREAD_INFORMATION[] Thre
private ulong CalculateRateValue(in ulong DeltaValue) {
if (DeltaValue == 0) return 0;
if ((LastUpdated - PreviousUpdate) <= 0) return DeltaValue;
return DeltaValue / (ulong)(LastUpdated - PreviousUpdate) / TimeSpan.TicksPerSecond;
return (ulong)Math.Round(DeltaValue / ((double)(LastUpdated - PreviousUpdate) / TimeSpan.TicksPerSecond));
}

/* Public Static Methods */
Expand Down
12 changes: 6 additions & 6 deletions src/Classes/TaskManagerSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,12 @@ public void Refresh(bool cancellingEvents = false) {
CpuUsageKernel.SetValue(_Cpu.KernelUsage);

// Compute ETW Usages
if (ETW.Running) {
ETW.Flush();
DiskRead.SetValue(ETW.Stats(0).DiskReaded);
DiskWrite.SetValue(ETW.Stats(0).DiskWroted);
NetSent.SetValue(ETW.Stats(0).NetSent);
NetReceived.SetValue(ETW.Stats(0).NetReceived);
if (Shared.ETW.Running) {
Shared.ETW.Flush();
DiskRead.SetValue(Shared.ETW.Stats(0).DiskReaded);
DiskWrite.SetValue(Shared.ETW.Stats(0).DiskWroted);
NetSent.SetValue(Shared.ETW.Stats(0).NetSent);
NetReceived.SetValue(Shared.ETW.Stats(0).NetReceived);
}

LastUpdate = DateTime.Now.Ticks;
Expand Down
4 changes: 2 additions & 2 deletions src/Forms/frmMain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ private void OnLoadParallelInit(object? sender, DoWorkEventArgs e) {
Stopwatch sw = new();
Extensions.StartMeasure(sw);
// We should use this to initialize something that is not really critical?
ETW.Start();
Shared.ETW.Start();
if (Shared.PrivateMsgID == 0) Shared.PrivateMsgID = API.RegisterWindowMessage(Application.ExecutablePath.Replace("\\", "_"));
// if (Shared.AddPrivilege("SeDebugPrivilege")) Debug.WriteLine("SeDebugPrivilege Set");
Shared.InitComplete = true;
Expand Down Expand Up @@ -186,7 +186,7 @@ private void OnClosingEventHandler(object sender, FormClosingEventArgs e) {
// If monitor is running we must stop it right now...
if (MonitorRunning) MonitorToggle();
if (_TrayUpdateTimer.Enabled) { _TrayUpdateTimer.Stop(); }
if (ETW.Running) ETW.Stop();
if (Shared.ETW.Running) Shared.ETW.Stop();
// Save Window Position & Tab...
if (Settings.RememberPositions) {
if (WindowState == FormWindowState.Normal) {
Expand Down
2 changes: 1 addition & 1 deletion src/Forms/tabPerformance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1368,7 +1368,7 @@ private void System_RefreshCompleted(object? sender, EventArgs e) {
meterNet.SetValue(System.NetworkUsage, System.NetworkUsageString);
chartNet.AddValue((double)System.NetReceived.Delta / 1024, (double)System.NetSent.Delta / 1024);
// Always flush the ETW, if its active.
ETW.Flush();
Shared.ETW.Flush();
}

private bool FullScreen {
Expand Down
10 changes: 5 additions & 5 deletions src/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
[assembly: AssemblyConfiguration("Release")]
#endif

[assembly: AssemblyVersion(".*")]
[assembly: AssemblyFileVersion("")]
[assembly: AssemblyInformationalVersion("")]
[assembly: GitCommit("")]
[assembly: BuildMark("1689993956")]
[assembly: AssemblyVersion("3.0.23.*")]
[assembly: AssemblyFileVersion("3.0.23")]
[assembly: AssemblyInformationalVersion("3.0.23")]
[assembly: GitCommit("gbbd4da60103107ed521589bf532f26c2a6ffe16e")]
[assembly: BuildMark("1690074458")]
Loading

0 comments on commit 0c1496a

Please sign in to comment.