Tuesday, November 25, 2014

WMI Filter Performance in Group Policy Objects

Hi all.

This is a follow-up to my previous post on WMI Filter Performance. I was curious about whether these findings for different kinds of WMI queries would have a noteable impact on GPO processing performance.

TL;DR: WMI filters in GPOs benefit from proper queries. Never "select * from" anything, always "select name" or whatever key property your class has. This simple change can speed up WMI filter evaluation by up to 95%.

To verify, I created a GPO with a simple ADM setting and linked a WMI filter to it. Then I created 200 copies of my GPO (PoSh Copy-GPO) and linked them to a testing OU (PoSh New-GPLink) with inheritance blocked. Combined with the WMI filter that has 5 queries, this results in a 1000x evaluation of the query itself.

My OU looks something like that:

(...and so on up to 200)

And this is my WMI filter:

(Silly, I know - but sufficient...)

My reasons to do 200 GPOs and a 5x WMI filter:
  1. GPMC gets really sluggish when dealing with huge numbers of GPOs - and I wanted to be able to provide some screen shots
  2. You cannot link unlimited GPOs to an OU - the gPLink attribute is limited in its size
Now let's check how this "mess" performs. I enabled GPSVC debug logging and did a gpupdate /force /target:user on a virtual machine that was running build 9841, one CPU, 2 GB.

CPU load went straight up to 100%, and with all my 200 GPOs and 1000 WMI queries, I got the following start and end GPSVC.LOG entries:

GPSVC(3d8.e58) 15:37:54:512 ProcessGPO(User):  Searching

GPSVC(3d8.e58) 15:45:35:854 ProcessGPO(User):  Found extensions:  [{35378EAC-683F-11D2-A89A-00C04FBBCFA2}{D02B1F73-3407-48AE-BA88-E8213C6761F1}]

So this is a 07:41 evaluation time. Remarkable...

Then I simply changed my 5 WMI queries according to my findings that we should not select *, but the key property:

Ran gpupdate again and checked results:

GPSVC(3d8.cb0) 16:10:22:602 ProcessGPO(User):  Searching

GPSVC(3d8.cb0) 16:11:09:368 ProcessGPO(User):  Found extensions:  [{35378EAC-683F-11D2-A89A-00C04FBBCFA2}{D02B1F73-3407-48AE-BA88-E8213C6761F1}]

Evaluation time went down to 00:47 - compared to the above 07:41, that's an enormous performance gain.

I finally deleted the WMI filter to get the "basic" time needed for evaluation:

GPSVC(3d8.cb0) 16:14:41:336 ProcessGPO(User):  Searching

GPSVC(3d8.cb0) 16:14:54:383 ProcessGPO(User):  Found extensions:  [{35378EAC-683F-11D2-A89A-00C04FBBCFA2}{D02B1F73-3407-48AE-BA88-E8213C6761F1}]

That's 00:13 for evaluation without any filters.

In other words: Basic evaluation time for 200 GPOs is about 65 ms per GPO (200 GPOs, 13 Seconds). WMI query evaluation time with proper queries is about 34 ms per query (with Win32_Service). Using an improper query pushes this time up to 458 ms per query.

That said - check your filters. And do it NOW!


  1. Greetings, You had previously posted a solution to a slow drive mapping problem, by using Item-Level targeting and this WMI query "select * from win32_Pingstatus where address="Fileserver" and statuscode=0"

    I'm not that well versed in WMI, how would one optimize that command?

  2. According to https://msdn.microsoft.com/library/aa394350.aspx, "address" is a key property of Win32_PingStatus. So the optimization would be
    select address from....
    As long as you do not use dozends of these filters, I doubt it will be noticeable. But ok, we are always doing research for small amounts of wasted time, which at the end of the day will sum up to several minutes :-)