Kernelzeit / PrivilegedProcessorTime

Haben Sie schon mal den Taskmanager ihres Exchange Servers angeschaut und sich über Kernel-Zeiten gewundert? Wo kommt das her?

Auslöser

Die CPU-Last auf einem Server ist ein wichtiger Indikator für die mögliche Leistungsreserven. Ein gutes Monitoring überwacht diese Counter und liefert ggfls. einen Alarm aber kann auch Trends über längere Zeiträume ermitteln. Allerdings ist die reine CPU-Zeit nicht alleine aussagekräftig, denn Windows unterscheidet zwischen "Usertime" und "PrivilegedProcessorTime". Letztere wird auch "Kernel Times" genannt. Hier mal zwei Server, die als VM einmal Exchange und einmal ein DC sind. Sie können auf ihrem Windows Server oder Client einfach den Taskmanager  (CTRL-SHIFT-ESC) starten und die Performance anzeigen lassen. Mit einem Kick auf die rechte Maustaste im CPU-Diagramm können Sie dann die Anzeige mit "Show kernel time" aktivieren. Hier sehen Sie einen Server der eine kleine unkritische Lastspitze hat aber ansonsten nichts tut. Das war mein Exchange Labor-Server.

Das zweite Bild zeit einen anderen Server auf der gleichen HyperV-Hardware, die eine gewisse Grundlast hat aber diese überwiegend von der Kernel-Time belegt wird.

Das ist natürlich schon mal interessanter, welcher Prozess hier den Server so beschäftigt.

Hier noch zwei Ansichten zweier physikalischer Server, die produktive Exchange 2019 Server  sind. Sie sind mit 256 GB Ram und 16 Cores ziemlich gut ausgestattete und nutzen sowohl HDDs als auch SSDs. Der erste Server ist beschäftigt und interessant ist, dass die Kernel-Zeit und User-Zeit quasi im Gleichtakt arbeitet. Wenn ein UserProzess mehr Dateizugriffe macht, muss der Filesystem-Treiber im Kernel auch mehr arbeiten. Klingt logisch.

Dann schaue ich mir aber einen anderen Server an, der eigentlich ein vergleichbares "Kernelniveau" hat aber nahezu 100% CPU-Last hat.

 

Das frag ich mich dann schon:

  • Ist so viel Kernelzeit normal?
  • Welcher Prozess hat hier so viel UserTime?
  • Was ist eigentlich Kernelzeit?

Task-Details

Ich habe mit den Server genauer angeschaut, der so eine sehr hohe Last hat. Der Taskmanager hat auch dazu eine Antwort. Die Übersicht der Prozesse zeigt zwar nur die CPU-Last und Memory-Nutzung aber für einen ersten Blick reicht dies

Wir sehen hier aber nur allgemein "CPU" in Prozent aber nicht genauer, welchen Anteil ein Prozess an der "Kernel Time" hat. Das sehen Sie leider auch nicht über die "Details"-Karteikarte, in der ich aber weitere interessante Spalten, z.B. "CPU Time" oder auch I/Os einblenden kann.

 

Der Server hat zwar eine hohe Last, aber das scheint nicht immer so zu sein. Ansonsten wäre der Wert "CPU time" des Prozess "System Idle Process" nicht so extrem hoch im Vergleich zu den anderen Prozessen.

Achtung: Ich sehe hier immer nur die aufsummierten Daten seit dem letzten Start. Beim Wert "System Idle Process" ist dies seit dem Start von Windows aber bei den anderen Prozessen muss dies nicht so sein.

Auf diesem Server sind zwei Instanzen des IIS schon kräftig aktiv und wenn ich nach "CPU Time" sortiere, dann ist schon ersichtlich, dass Exchange einen großen Anteil hat.

 

Es muss also Zeiten geben, in denen der Server weniger zu tun hatte. Welcher Application Pool sich hinter welchem w3wp.exe versteckt, sehen Sie am besten über die Kommandozeile, welche Sie ebenfalls einblenden können

Über den Weg können Sie oft auch erkennen, mit welchem Skript eine PowerShell gestartet wurde.

Einfluss der CPU-Kerne

Bei der Berechnung der CPU Zeit muss man natürlich die Existenz mehrerer CPUs bedenken. Wird die Zeit mit der Anzahl der CPUs multipliziert oder schon von Windows normalisiert? Ich habe mir dazu die Uptime" des Servers geholt und umgerechnet. Die Uptime von etwas über 70 Tage ergibt nur 1680 Stunden. Das ist viel zu wenig für die 18557 Stunden CPU-Zeit. Wenn ich mir den Taskmanager anschaue, dann springen die Sekunden beim "System Idle Prozess" auch immer mehrere Sekunden. Ich muss den wert also mit den CPUs multiplizieren und komme damit auf 26880 Stunden. Das bedeutet aber auch, dass die anderen Prozess in der Summe 8323 Stunden benötigt haben. Die Server-CPU ist im Mittel nur zu ca. 30% ausgelastet.

Das ist natürlich keine legitime Rechnung, denn wenn der Server 8h tagsüber auf 100% läuft und die Anfragen der Anwender verzögert bearbeitet werden, dann hat niemand etwas davon, wenn der Server nachts die restlichen 16h quasi "Idle" wäre. Es bedeutet aber auch, dass eine hohe Last von vielleicht 60-90% nicht automatisch für einen "langsamen Server" stehen. Es kann ja durchaus sein, dass der Client dies durch Cache-Mode nicht mehr, oder die Prozess eine niedrigere Priorität haben und sofort zurückstehen, wenn wichtigere Prozesse anstehen.

Wir können aber z.B. für jeden Prozess den Zeitpunkt des Starts ermitteln und über die Anzahl der Cores die CPU-Sekunden seit dem Start errechnen und so prozentual den Anteil an der Last ermitteln.

Ich weiß nur noch nicht, wie sich Virtualisierung hier niederschlägt, d.h. wenn eine virtuelle CPU gar nicht "dran" ist. Das wäre es ja nicht fair, die Zeiten dazu mitzurechnen.

Auch CPUs können je nach Energieeinstellungen ja ihre Taktrate verändern und der Exchange Health Checker prüft dies sogar:

$processor = Get-WmiObject -Class Win32_Processor
$throttled = $processor | Where-Object {$_.CurrentClockSpeed -lt $_.MaxClockSpeed}
if ($throttled) { 
   Write-Host ("Throttling your CPU")
}

Bei Servern sollte der Energiesparplan zumindest bei Exchange aber auf "Höchstleistung" stehen, aber erwarten sie besser keine absoluten Zahlen, die am Ende genau aufgehen.

Lücken in der Erfassung

Get-Process kann immer nur die aktuell aktiven Prozesse erfassen und die von diesen genutzte Prozessorzeit abfragen. Sobald ein Prozess von Windows aber beendet wird, verschwindet er aus der Taskliste und damit auch alle Informationen über seine bisherige Belastung der Ressourcen. Das Betriebssystem räumt auf. Ein Rückblick auf früher beendete Prozesse gibt es nicht. Nur der "Idle"-Prozess könnte die Information liefern, aber hat diese Daten nicht.

 

Das bedeutet natürlich auch, dass Sie bestimmte Workloads gar nicht finden können, wenn Sie nicht oft genug nachfragen. Wenn z.B. eine Monitoring-Lösung wie Splunk alle 5 Minuten ein PowerShell-Script startet, um bestimmte Daten ihres Servers abzufragen, welches danach wieder beendet wird, dann wird die CPU-Belastung nicht auf den aufrufenden Prozess drauf addiert. Nun wird ein Skripte, welches nur ein paar Sekunden läuft, natürlich auch keine sehr hohe Last auf Dauer produzieren und hoffentlich haben Sie keine Software, die die jede Aufgabe einen eigenen Prozess instanziert. Threads in einem Prozess werden schon dem Prozess zugerechnet.

Die Aussagekraft der Werte hängt auch mit den Berechtigungen zusammen. Alle Details bekommen sie nur, wenn Sie die Abfragen als Administrator durchführen. Als normaler Benutzer sehen Sie zwar auch alle Prozesse aber nicht alle Details. Besonders die Zeiten als auch die "CommandLine" sind dann nicht vollständig. Das ist aber erwartet und auch gut so.

Auf Servern ist das weniger relevant aber auf Clients müssen Sie auch damit rechnen, dass ein System in den Schlafmode versetzt wird und damit zwar läuft aber doch nicht läuft. Es vergeht also "Zeit" ohne dass die Prozesse etwas tun. Das kann die ermittelte CPU-Belastung natürlich niedriger erscheinen lassen, als dies real ist. Auswertungen auf Basis der benötigten Zeit im Bezug auf die vergangene Zeit sind daher mit Vorsicht zu betrachten.

Ich habe mit mal die "KernelModeTime" des "Idle"-Prozess ausgeben lassen und den Notebook nach 2h wieder aufgeweckt. Die Zeit ist ohne Sprung weitergelaufen, d.h. es sollte wirklich die verfügbare Zeit sein.

Es muss aber gar nicht der Schlafmode sein. Es reicht schon ein "Energiesparplan", der eine CPU mangels Aktivität dazu bringen kann, die Taktrate zu reduzieren und damit schon generell weniger schnell arbeiten würde. Ein Prozess würde dann bei relativer Betrachtung prozentual mehr CPU-Last erzeugen. Allerdings sind CPUs sehr schnell beim Anpassen der bereitgestellten Leistung.

Es gibt meines Wissens aber keinen Counter der die Gesamt CPU-Zeit eines Systems enthält, die seit dem Start bereitgestellt war. In den Details des Taskmanagers sehe ich aber den Zeitraum des "Idle"-Prozess:

 

Allerdings liefert Get-Process diese Information nicht aus. Ich komme aber per WMI oder CIM an diese Daten:

PS C:\> Get-WmiObject Win32_Process -Filter "Name='System idle process'" | Format-List Name, KernelModeTime

Name           : System Idle Process
KernelModeTime : 3387797656250

PS C:> Get-CimInstance Win32_Process -Filter "name = 'System idle process'" | select name,KernelModeTime

Name           : System Idle Process
KernelModeTime : 3387797656250
 

94 Stunden im Taskmanager  sind ca. 5640 Minuten oder 338.400 Sekunden, was recht nahe an 338.779.765.6250 kommt. Die Auflösung des WMI-Counter ist wohl 100 Nanosekunden. So komme ich dann auf

[timeSpan][long](Get-CimInstance Win32_Process -Filter "Name='System idle process'").KernelModeTime

Die drei Tage sind keine echten Tage, da mein Computer mehrere CPUs hat. Auch hier laufen die Sekunden deutlich zu schnell.

while ($true) {
   ([timeSpan][long](Get-CimInstance Win32_Process -Filter "Name='System idle process'").KernelModeTime).totalseconds
   start-sleep -Seconds 1
}

 

Jede Sekunde springt die durch den "Idle"-Prozess verwendete Zeit um ca. 8 Sekunden vor, da mein alter Intels Core i7-8550U einen Socket mit 4 Cores und mit Hyperthreading 8 logische CPUs hat.

Übrigens gibt es noch den "System"-Prozess, der auch keine UserModeTime hat, sondern 100% in KernelModeTime verbringt.

Ich könnte mir vorstellen, dass dies dann der Kernel selbst ist. Bei mir waren das ca. 47 Minuten, während der Idle Prozess ca. 6225 Minuten genutzt hatte und damit gerade mal 0,7% meiner CPU benutzt hat.

Was ist Kernel Time?

Wer im Studium oder Ausbildung etwas über Betriebssysteme gehört hat, sollte wissen, dass moderne Multitasking-Systeme verschiedene Prozessräume und Privilegien nutzen und ziemlich tief unten der "Kernel" als zentrale Komponente fungiert. Er stellt quasi die Plattform dar, auf der alle anderen Programme dann aufsetzen. Der Kernel sorgt dafür, dass Programme "dran" kommen, denn es gibt fast immer mehr parallel laufende Programme als CPU-Kerne, die die Arbeit ausführen. Also gibt es einen Scheduler der Zeitscheiben nach Prioritäten vergibt. Der Kernel muss sich aber auch um die Ansteuerung gemeinsam genutzter Komponenten, z.B. Hauptspeicher, Massenspeicher, Netzwerk und Bildschirmansteuerung kümmern. Die dazu erforderlichen Treiber werden vom Kernel nachgeladen und haben entsprechende Prioritäten. Diese Verarbeitung benötigt selbst natürlich auch CPU-Zyklen. Moderne CPUs unterstützen den Kernel durch besondere Befehle und Konzepte, damit Programme eines Benutzers nicht einen Speicherbereich von anderen Programmen oder sogar des Kernels überschreiben können.

Nun haben wir aber gesehen, dass es bei jedem Prozess neben einer "Usertime" auch eine "Kerneltime" gibt. Das widerspricht erst einmal der Sicht auf den eigentlichen "Kernel". Damit ist aber gemeint, dass das Program, welches in seinem UserSpace läuft, natürlich z.B. Zugriffe auf Dateien und Netzwerkschnittstellen nutzen, die vom Kernel über Schnittstellen bereitgestellt werden. Die Zeit, der der Kernel hier für die Verarbeitung benötigt, wird dem UserProzess als gesonderte Zeit zugeschlagen. Das bedeutet aber nicht, dass damit der aufrufende Code die Rechte des Kernels hätte. Die "Kernel Time" ist quasi die Zeit, die eine Applikation beim Aufruf von Kernelfunktionen verbringt.

Ein Server sollte primär Zeit für seine User-Prozesse haben und die Kernel-Dienste sind meist nicht "rechenintensiv". Der Anteil der Zeit im Kernel sollte zwischen 5-10% der kompletten Prozessorzeit sein und möglichst 20% nicht überschreiten.

In den Bildern am Anfang habe ich gesehen, dass UserTime und KernelTime miteinander geknüpft sind. Das ist auch zu erwarten, denn wenn ein Prozess unter UserTime eine Aktion ausführt, dann ist meist ein Disk-IO, Netzwerk-IO o.ä. involviert, die als Kerneltime läuft. Vermutlich sind dann nur Crpto-Trojaner oder andere Miner primäre im UserSpace unterwegs.

Es kann daher sinnvoll sein, sich bei Massenspeichern die übertragene Datenmenge oder noch mehr die Latenzeit anzuschauen. Auch beim Netzwerk ist eine hohe Anzahl an Paketen/Sek eine gute zweite Meinung bei einem hohen Anteil der Kernel Zeit an der Gesamtbelastung.

Auswerten mit Perfmon

Das folgende Bild zeigt einen Server, auf dem anscheinend relativ wenig im UserSpace los ist und deutlich mehr CPU im Kernelspace benötigt wird. Das kann natürlich die "Selbstverwaltung" des Betriebssystems sein, ein Zeichen auf viele Netzwerkpakete, die der Kernel dann aber verwirft oder Probleme mit einem Treiber. Wir wissen es aber nicht und eine Analyse des Kernes selbst ist nicht so einfach. 

Aber es gibt den Performance Monitor, mit dem wir die Prozess mit ihren Zeiten und Lasten anzeigen können. Aber selbst auf meinem Desktop laufen 485 Prozesse und so viele Counter kann ich in Perfmon gar nicht sinnvoll anzeigen.

Helfen können aber die "Data Collector Sets", die Windows als Bordmittel enthält. Wenn Sie hier das Set "System Performance" starten, dann sammelt das Programm über 60 Sekunden viele Counter erst einmal ein:

Danach können sie den Mitschnitt unter "Reports" einsehen. Auf einen Blick sehe ich nicht nur die "Big Four" (CPU, DISK, RAM, NET) sondern auch direkt Details zum aktivsten Prozess

Hier kann an sehen, dass CPU, Netzwerk und Disk eigentlich kein Problem haben aber aus Sicht von Windows der Speicher mit 85% schon belastet ist. Allerdings sind 15% "free" bei 256GB immer noch 40 GB frei und kein Grund zur Sorge. Sie sehen, dass relative Werte durchaus kritisch zu hinterfragen sind.

Weiter unten (nicht angezeigt), können Sie dann in die Details zu Prozessen, Services, Netzwerk, Disk (aktive Dateien) etc. eintauchen. Dort wird dann auch die "PrivilegedProcessorTime" angezeigt. So richtig geholfen hat das bei mir aber nicht.

Auswerten mit PowerShell

Daher habe ich mich weiter auf die Suche begeben, wie ich genau meine Thematik ermitteln kann. Ich wüsste gerne, welcher Prozess für eine erhöhte PrivilegedProcessorTime verantwortlich ist. Dabei geht es nicht allein um den absoluten Wert, denn wenn ein Prozess eine wichtige Funktion ausführt und entsprechende Usertime hat, dann wird er auch PrivilegedProcessorTime haben. Wenn auf dem kompletten Server aber nur ganz wenig UserTime benötigt ist, dann sollten die fraglichen Prozesse auffallen.

Auf der Suche nach einer Prozessliste habe ich mehrere Wege gefunden, diese zu ermitteln. Ich habe mich auf die PowerShell 7 beschränkt aber PowerShell 5 solle genauso gehen.

# Nativer Befehl, der leider keine Kommandozeile liefert
Get-Process -name Powershell

Get-WmiObject Win32_Process -Filter "name = 'powershell.exe'" | Select-Object CommandLine

Get-CimInstance Win32_Process -Filter "name = 'powershell.exe'" | select CommandLine

Bei Get-Process können Sie den Namen der Prozesse als Filter angeben und die Rückgabe liefert auch jede Menge Counter und Werte.

Allerdings habe ich mich später dann doch für Get-CIMInstance entschieden, da damit auch die CPU-Zeit des "Idle"-Prozess erfasst wird, welche Get-Process nicht liefert.

Da ist eigentlich alles drin, was ich brauche. Mich interessieren folgende Properties:

  • CommandLine
    Diese Feld ist interessant, denn es gibt einige Dienste und Prozesse, die den gleichen Namen haben, weil Sie vom gleichen Host gestartet werden. Meist ist das "SVCHOST.EXE" und "W3SVC.EXE". Über die "Commandline" kann ich aber beim IIS z.B. den AppPool unterscheiden und bei SVCHost zumindest einige Dienste. Leider ist das nicht immer eindeutig aber besser als nichts.
  • StartTime
    Zeitpunkt, wann der Prozess gestartet wurde. Ich subtrahiere diese Zeit von der aktuellen Zeit und habe dann die Dauer, die der Prozess schon läuft. Multipliziere ich dies mit der Anzahl der CPU-Cores, dann habe ich die Gesamt-CPU-Zeit als Basis für prozentuale Angaben
  • KernelModeTime
    Das ist dann der Anteil der Zeit im Kernel in "Ticks", wobei ein Tick für 100ns steht. Bei Get-Process wird der Wert als "PrivilegedProcessorTime" als Zeit ausgegeben,
  • UserModeTime
    So viele Ticks in 100ns hat der Prozess im UserSpace verbraucht. Bei Get-Process ist dies als Zeit in "UserProcessorTime" aufgeführt.

Leider gibt es keinen zuverlässigen Counter, der die Summe alle "Ticks" aufführt, seit dem das System gestartet wurde. "System" und "Idle" zu addieren hilft nicht, wenn der Computer "busy" ist aber die Prozesse dazu nicht durchlaufen. Also muss man alle Zeiten addieren.

Ich habe auch mal versucht die Ticks einfach anhand der CPU-Anzahl zu ermitteln, aber das ist nicht sinnvoll. CPUs sind zu dynamisch mit ihren P- und E-Cores. Die Anzahl bekomme ich per WMI oder CIM.

Get-CimInstance Win32_Processor |ft name,NumberOf*

Mit den Daten kann ich nun folgende Werte ermitteln, wenn ich zwei Messungen in einem definierten Abstand vornehme.

  • TotalProcessorTicks
    Die Gesamtzahl der Ticks ermittel, ich, indem ich einfach alle Kernelzeiten und UserZeiten aller Prozesse addiere.
  • TotalKernelRelative: Relativer Anteil des Prozess an Kernelzeit
    Dazu nehme ich die Differenz der "KernelModeTime" der zwei Messungen und teile Sie durch die TotalProcessorTicks. Damit sollte ich die Prozesse finden, die quasi im Ruhezustand viel Kernel-Last machen.
  • UserModetoKernelmode
    Wenn ein Prozess mehr Arbeit im UserMode hat, dann sind höhere Kernelmode-Aufwände zu erwarten aber das Verhältnis muss passen. Daher Teile ich die KernelmodeTicks durch die Summe aus KernelmodeTicks  und UserModeTicks. 1 wäre dann 100% Kernelmode und 0,5 dann für ein 1:1-Verhältnis.

Natürlich könnte man die Ausgabe noch auf Speicherveränderung, IO-Veränderung etc. erweitern. Mein Ziel war es aber erst einmal eine hohe Kernel-Grundlast auf einem Server genauer zu ergründen.

Skript

Die Erfassung passt natürlich nicht mehr in eine Zeile, sondern wurde eine PS1-Datei mit Parametern.

Hier sehen Sie die Default-Einstellungen, welche im Abstand von 60 Sekunden eine Prozessliste ermitteln und die Ausgabe sowohl in die Pipeline als auch in eine CSV-Datei schreiben. "repeatcount=0" beendet das Skript nach einem Intervall. Zudem speichere ich den letzten Status in der durch $lastrunfile spezifizierten Datei. Wenn ich so das Skript das nächste Mal starten, liest es den letzten Status aus dieser Datei und misst sofort die Ergebnisse. Hier ein paar exemplarische Aufrufe

# Alle Prozesse mit den Standardwerten (einmal mit 60 Sekunden erfassen und in CSV-Datei protokollieren
.\kernelzeit_privilegedprocessortime.ps1

# Alle Prozesse im Abstand von 5 Sekunden insgesamt 10 Mal abfragen
.\kernelzeit_privilegedprocessortime.ps1 -interval 5 -repeat 10

# Genauere Betrachtung der "Outlook Prozesse" für 10 Minuten 
.\kernelzeit_privilegedprocessortime.ps1 -filter "name LIKE '%outlook%'" -interval 5 -repeat 120

# Alle Prozesse ca 10 Minuten im 5 Sek Intervall abfragen und die 
.\kernelzeit_privilegedprocessortime.ps1 -repeat 5 -interval 120 | where {$_.TotalKernelRelative  -gt 0}

Eine Auflösung von unter einer Sekunde halte ich nicht für sinnvoll. Beachten Sie, dass sehr hohe Repeat-Zahlen die ggfls. angegeben CSV-Datei wachsen lassen. Auf meinem Desktop mit 423 Prozessen ist eine Momentaufnahme ca. 150kbyte groß, da es 423 Zeilen mit vielen Daten in der CSV-Datei sind. Für längere Auswertungen sollten Sie daher die CSV-Dateien abschalten und stattdessen die Ausgabe filtern und selbst wegschreiben z.B. mit:

# Alle Prozesse ca 10 Minuten im 5 Sek Intervall abfragen und die Top10 ausgeben 
.\kernelzeit_privilegedprocessortime.ps1 -repeat 5 -interval 120 -csvfile $null `
   | select "timestamp","ProcessID","ProcessName","TotalTimeDelta","KernelModeTimeDelta","TotalKernelRelative","KerneltoUserMode" 
   | where {$_.TotalKernelRelative -gt 2} `
   | export-csv .\kerneltimetrace.csv

kernelzeit_privilegedprocessortime.ps1 

Windows führt leider nicht Buch über Prozess. Der Vergleich des aktuellen zu einem älteren Stand ist nicht immer akkurat, z.B. wenn Prozess schon länger beendet wurden. Die Ergebnisse sind nicht als absolute Werte zu verstehen sondern helfen bei der Suche nach Prozessen, die z.B. einen hohen Anteil an der Kernellast haben.

Wer den Parameter "-Verbose" verwendet, sieht etwas mehr Details.

Auswertung

Ich habe das Skript mit folgenden Parametern gestartet: Mir reichte ein Messinterval von 5 Sekunden und danach habe ich die Ergebnisse in eine Variable gespeichert. Mich interessieren die Prozess, mit einem hohen Anteil am CPU-Zeit, so dass ich nach "TotalTimeDelta" absteigend sortiert habe. Sie sehen gut, dass "System Idle Process" sehr hoch sind aber in der Zeit auch "Outlook.exe" einiges an Zeit (210Mio Ticks) belegt hat und dabei 35% im Kernel unterwegs war.

Je weiter es nach unten geht, desto weniger CPU-Anteile entfallen auf die Prozesse bis am Ende viele Prozesse auch mit 0 Ticks aufgeführt werden, weil sie einfach nichts getan haben.

Interessant ist bei so einer Auswertung natürlich ein längeres Intervall, z.B. von einer Minute und die Speicherung der Daten in der CSV-Datei oder als Versand an Enterprise-Dienste wie Splunk etc., die dann auf dem Prozess Diagramme erzeugen können

Eine Einbindung in einfachere Monitoring-Lösungen wie PRTG muss ich noch prüfen, denn die Prozessliste ist natürlich schon lange und ein Diagramm mit 400 oder mehr Linien ist nicht brauchbar. Die "Top 10" hilft aber auch nicht, wenn die Prozesse wechseln. Daher belasse ich es erst einmal bei der CSV-Datei, die ich mit Excel, PowerBi oder auch wieder PowerShell entsprechend auswerten kann. In der CSV sind auch weitere Felder und ein Zeitstempel enthalten.

Die Spalten sind:

  • "timestamp"
    UTC-Zeitstempel, der auch als String sortierbar ist
  • "ProcessID"
    Nummer des Prozess
  • "ProcessName"
    Ausgeführte EXE ohne Pfad
  • ServiceName
    Ich versuche anhand der Kommandozeile und des Prozess beim IIS (w3wp.exe) den Exchange AppPool zu ermitteln und bei Diensten den richtigen Dienstnamen. Das ist aber nicht 100% zuverlässig.
  • "KernelModeTime"
    Absolut im Kernel verbrachte Zeit in CPU-Ticks (100ns) seit Start des Prozess
  • "UserModeTime"
    Absolut im Userspace verbrachte Zeit in CPU-Ticks (100ns) seit Start des Prozess
  • "TotalTimeDelta"
    Summe von KernelModeTime und UserModeTime" in CPU-Ticks (100ns) seit Start des Prozess. Man könnte damit eine durchschnittliche CPU-Nutzung über die ganze Laufzeit des Prozess abschätzen.
  • "KernelModeTimeDelta"
    CPU-Ticks (100ns) im KernelMode seit der vorherigen Messung
  • "UserModeTimeDelta"
    CPU-Ticks (100ns) im UserMode seit der vorherigen Messung
  • "TotalKernelRelative"
    Prozentualer Anteil im KernelMode bezogen auf die Gesamtzeit seit der Messung. Wenn ein Prozess z.B. 10% Kerneltime verursacht, steht hier eine 10. Der Wert hilft gut dabei, zu ermitteln, welche Prozess hier zu viel Kernelzeit benötigen könnte
  • "KerneltoUserMode"
    Verhältnis zwischen KernelTime und UserTime. In der Regel hat ein Prozess sowohl UserTime als auch KernelTime. Der viel Kernelfunktionen (Disk, Netzwerk etc.) aufruft, hat hier höhere Werte. 100% = nur Kernelzeit.
  • "Commandline"
    Kommandzeile beim Aufruf
  • "CreationDate"
    DateTime zu dem der Prozess gestartet wurde

Aktuell ist das Skript ein Diagnosewerkzeug in meinem Werkzeugkasten. 

Weitere Links