WMI ist (k)ein Performance Killer

07.10.2021 | Autor: Mark Heitbrink

WMI ist kein! Performance Killer.

Die Aussage das WMI ein Performance Killer ist, ist nicht haltbar. Es ist ein Festhalten an uralten Wissensstand, derjenigen, des es niemals korrigiert, getestet oder probiert haben. Man hat das irgendwann einmal gelesen und dann akzeptiert. Die Aussage, das WMI in Gruppenrichtlinien eine Spassbremse ist, höre ich bei jedem Kunden und viele Consultants empfehlen es immer noch als Performance Killerfeature, den sehr hilfreichen Filter auszulassen.

Der Hauptvorwurf an WMI:

  • WMI ist Prozessorlastig

A brief history of time

Wir reden vom Jahr 2002. WMI als Filter der Gruppenrichtlinien wurde mit Windows XP eingeführt. Wir reden von Intel® Celeron® (1998), Intel® Pentium III® (1999), Intel® Pentium 4® (2000), den ersten Intel® Pentium® 4 Notebookprozessor-M und etwas später dann den ersten Dual Core Porzessoren, wie Intel® Core™ 2 Duo (2006). Quelle

Diese Art von Prozessoren waren zu der Zeit im Einsatz und die Schätzchen waren im Vergleich zu heute, i5/i7 11te Generation Schnecken und unglaublich langsam. Mit der Einführung von Windows 7 (erste Public beta Januar 2009) hat Microsoft massiv an der Performance des lokalen WMI Store und des Dienstes gearbeitet. 

Tag heute haben wir 4/6 oder gar 8 Kerne in den CPUs, "Bumms" ohne Ende, aber der Vorwurf das WMI prozessorlastig ist, steht immer noch im Raum.

Abhilfe gegen altes Wissen: Testen und Messen

WMI ist hochperformant und ein perfekter dynamischer Filter in einer starren AD Struktur, wenn ...

  • ... die Query ordentlich gebaut wurde
  • ... die Query lokal bleibt und nicht ins Netzwerk fragt
  • ... die Query keine Dateien auf einer sich drehenden Festplatte abfragt
  • ... die Query kein riesiges "Datenblob" abruft

Test Szenario:
wir nutzen das measure-Command cmdlet, um die Query zu messen. Die erste Query sollte immer in einer neugeöffnenten Powershell erfolgen, da bei der 2ten Abfrage desselben Werts, dieser aus dem Cache kommt. Was uns andereseits im Prozess der Gruppenrichtlinien zugute kommt. Wenn ihr 10mal dieselbe Query stellt, dann kommt sie bei den letzten 9 Abfragen aus dem Cache und ist schneller (Faktor 3 - 4).

Fehler 1: Schlecht gebaute Querys

 

measure-Command {Get-WmiObject -query "SELECT * FROM Win32_OperatingSystem WHERE ProductType = '1'"}

 

Die Antwort sollte in ca. 150ms zurückkommen, beim 2ten Aufruf sind es nur noch ca. 50ms. Apropos Performancekiller. 150ms ist nicht wirklich langsam, oder? Was ist also schlecht an der Query? Es ist das "select *". Jeder der ein wenig mit SQL zu tun hat, weiss das man niemals nach allem (*) fragt, wenn man nur eine Antwort möchte.

Korrektur Fehler 1:

 

measure-Command {Get-WmiObject -query "SELECT ProductType FROM Win32_OperatingSystem WHERE ProductType = '1'"}

 

Alleine durch die Korrektur sollten die Zeiten sich auf ca 50ms und 15ms reduzieren. Es bleibt nur noch ein knappes Drittel. Alleine durch das weglassen des "*" und der gezielten Abfrage des Wertes. Noch mal zum mitschreiben: 50ms. 50! Millisekunden! 
Wieviele Filter benötige ich, bei 50ms, damit beim Anwender ein spürbarer Warteprozess beim Start und der Anmeldung auftaucht? Selbst eine aufwendige Query, die lokale simple Daten abfragt ist sehr schnell.

 

measure-Command {Get-WmiObject -query "SELECT Name,ProductType,OSArchitecture,CountryCode FROM Win32_OperatingSystem WHERE Name LIKE '10%' AND ProductType = '1' AND OSArchitecture = '64-Bit' AND (CountryCode = '49' OR CountryCode = '01')"}

 

In meinem System nur minimal langsamer als die vorherige: 60ms bei erster übernahme, unter 20ms bei den weiteren.

Fehler 2: Das Dateisystem fragen

 

measure-Command {Get-WmiObject -query "SELECT FileName,Path FROM CIM_DataFile WHERE Filename = 'winword' AND path = '\\program files\\Microsoft Office\\root\\Office16'"}

 

Das Dateisystem auf einer SSD abfragen ist zeitlich akzeptabel kostet aber im Schnitt mehr Zeit als die simplen Werte im ersten Beispiel. Bei einer sich drehenden Festplatte kann der Wert um ca. Faktor 10 erhöht werden. Als ich es das letzte Mal getestet habe lagen die Abfragen bei ca. 800ms pro Query. Das ist für einen einzigen Filter eventuell akzeptabel, aber bei 3 oder 5 davon ist es spürbar am Client. Davon abgesehen gibt es noch Spindeln am Client? Ich hoffe nicht.

Korrektur Fehler 2:

Das Dateisystem nicht mehr als einmal fragen und SSDs einbauen.

Fehler 3: ein riesen Datenblob abfragen

 

measure-command {Get-WmiObject -query "Select Name from Win32_Product where Name like '%Microsoft Office%'"}

 

Das ist der Performance Killer. Das "Name" Feld enthält jede installierte Software des Systems. Je mehr Software, desto langsamer. Die Abfrage hat Laufzeiten von 20 Sekunden und noch mehr. Das ist jenseits jeder nutzbaren Filtertechnik. Das ist nicht akzeptabel. Das ist eine spürbare Wartezeit für den Anwender.

Korrektur Fehler 3:

Einfach nicht machen. Überlegen, ob es nicht ein andere Möglichkeit gibt zu erkennen ob Office installiert ist, zum Beispiel die Class Win32reg_AddRemovePrograms oder sogar das Dateisystem fragen. Das ist zwar nicht das Beste, aber immer noch im akzeptablen Bereich.

Fehler 4: eigentlich 3b

Mein Dank an Thorsten Meringer für den Link und das Statement: "Niemals win32_product verwenden!"

Windows Installer reconfigured all applications - Windows Server | Microsoft Docs

[...] Dieser Vorgang startet auch eine Konsistenzprüfung der installierten Pakete, der überprüfung und der Reparatur der Installation [...]

Fazit:

WMI ist wie ein Anmeldeskript. Wenn es schlecht programmiert ist, kostet es unglaublich viel Zeit. Keiner behauptet pauschal, das Anmeldeskripte Performance Killer sind. Macht das bitte auch nicht mehr mit WMI. Wenn ihr ein "wait 30" in das Skript einbaut und eure Performance stirbt, dann ist nicht das Skript schuld an der Laufzeit. Ehrlich nicht. Genauso ist das mit WMI. Man kann mit WMI coole Filter bauen, die einem in einer bestimmten Situation unglaublich im Regelwerk der GPOs helfen. Ihr solltet sie nur vorher testen.

Wie gesehen erzeugen triviale Abfragen wie "bist du ein Windows 10" oder "bist du ein Server oder Client OS", "bist du 64-Bit" und ähnliches keinerlei spürbare Wartezeit am Client. Wenn 10 WMI Filter gerade mal eine Sekunde Wartezeit ergeben, dann habe ich als Administrator sicherlich andere Baustellen, wo ich Performance verliere und wo ich mehr erreichen kann, wenn ich sie verändere.

Aufgrund der möglichen schlechten WMI Queries kommt es nach 30 Sekunden zu einem Timeout im GP Übernahmeprozess und die Query wird FALSE gewertet. Aber ihr wisst ja jetzt, wie ihr schöne performante Queries baut.

Eure Hausaufgabe für heute: "*" entfernen und umbauen.