Thursday, November 27, 2014

Showdown - WMI Filter vs Item Level Targeting

Hi all.

Again, it's "performance tune-up" time :-)

TL;DR: If you need filtering for GPOs and GPPs, do as little filtering as you can. If you use GPP, put all items for one area into one GPO (registry or printers, eg). If you filter for Registry Items, use collections where possible. And if you have to decide whether to use WMI filter or ILT, it depends - on the cost of your query, on the cost of invoking a GPP CSE just to find it will be filtered anyway, and on the cost of the number of GPP items with filters you have.

In my previous post, I examined WMI filter performance when using SELECT KeyProperty instead of SELECT * in WMI filters for group policy objects. This proves that WMI filters in GPOs behave exactly the same as when executed on a commandline  Now the question came up: What about Group Policy Preferences Item Level Targeting (ILT)? Does it perform better, equal or worse than WMI filters?

Preparing the testing scenario

To verify, I used almost the same setup as before: A testing OU where I blocked inheritance. A simple GPO with a registry preference item. This GPO I copied 200 times and linked all copies to my testing OU. A WMI filter with 5 queries, and an ILT filter with 5 conditions. Since I needed "comparable" queries and filters, I used WMI Win32_Battery and ILT Battery.

Remark: This test scenario requires modyfing a lot of GPOs - adding a WMI filter (which is impossible through PoSh, unfortunately), changing ILT settings and so on. I simply used some lines of PoSh to accomplish that after doing the required changes in my template GPO "WMI vs ILT":

$GPOName = "WMI vs ILT"
$DN = "OU=WMI-Test,OU=Backoffice,OU=Users,OU=Corp Root,DC=corp,DC=contoso,DC=com"
for ( $i=1; $i -le 200; $i++ ){
    Remove-GPO -Name "$GPOName - $i";
    Copy-GPO -SourceName "$GPOName" -TargetName "$GPOName - $i";
    New-GPLink -Name "$GPOName - $i" -Target $DN;

This is what my WMI filter looks like:

(Silly, I still know, but still sufficient... Nonsense anyway, because a WMI filter fails when the first query fails.)

And this is what my ILT looks like - I did one ILT using WMI queries and one ILT using the pre defined "Battery" condition. I OR'ed these conditions - AFAIK ILT skips evaluation for AND conditions as soon as the first condition is not met, very much the same like WMI filters do.

(This is the same gobble-di-goo as in the WMI filter...)

(Silly again, but sufficient, too...)

For measurement purposes, this time I opted to use Group Policy Eventlog. I filtered for specific Event IDs, namely 5311 (the last event before GP evaluations starts), 5312 (the first event after GP evaluation finishes) for GPO evaluation and 4016/5016 for GPP extension processing start and end. A list of all GP events can be found in this technet article.

To verify whether CPU performance matters, I used a VM with four virtual processors. I already know WMI filters are single threaded, so they will not benefit from the additional processor power. But I don't know about ILT right now, so let's check this, too... Remaining VM data: Windows 8.1 64 Bit with Update, 8 GB RAM.

Measuring the baseline

The first thing I did was applying my 200 GPOs without any filtering. This gives me the baseline for the time needed anyway for GP Evaluation and Registry Extension Processing. This baseline must be subtracted when comparing WMI and ILT performance in the other tests.

So, our baseline is 14 seconds for evaluating 200 GPOs without WMI filters (~70 ms for each GPO, events 5311/5312). It takes about 46 seconds to process 200 disabled registry items (the highlighted 5016 event) with an "update" action (~230 ms for each item). CPU load was about 25% all the time, which indicates that gpsvc is a completely single threaded process.

Remark: For this test, the registry item was disabled so no registry action happened that could delay the test. In all other tests, the registry item was enabled, but never applied due to filtering - my VM obviously has no battery.

1st Test: WMI filter

Lets verify how the WMI filter performs.

This is a total evaluation time of 27 seconds. Subtracting the baseline time gives 13 seconds for WMI filter evaluation (~6.5 ms for each individual query). Not too bad. And if you wonder why it's 6.5 ms and not 1.3 ms - WMI filters fail when the first query fails. So we only evaluated 200 filters and not 5x200=1000 filters.
The WMI filter for Win32_Battery takes about 7 ms.

2nd Test: ILT with WMI query

The following tests were done after removing the WMI filter and implementing ILT for our registry item. First, let's do the WMI ILT - I expect this to perform equally to the WMI filtering.

Subtracting our baseline (46 seconds) gives 73 seconds, which means 7.3 ms for each query (since we OR'ed the queries, we have 1000 queries to execute). Given that we are testing in a VM and in a multitasking environment, that's almost identical to the WMI filter above. To be honest, that is the expected result.

The ILT WMI query for Win32_Battery takes about 7 ms.

Remark: I verified these 7 ms with PoSh Measure-Command earlier in this blog post where it took about 8.5 ms, but on a less powerful VM. That, too, is almost equal.

3rd Test: ILT with "Battery"

Then I changed the ILT from WMI to Battery, as shown in the screen shots at the beginning.

After subtracting the baseline, this filter lasts 63 seconds which is not a huge gain over the WMI query, but it is a notable gain. We are happy about time savings where ever we can find them, and this one are about 15%. Ok, if we only use one ILT, it is a gain of one millisecond. You get the picture :-)

The ILT Battery query takes about 6 ms.

Remark: In this scenario, the WMI filter would be the perfect choice. Not because it is faster, but because it removes the Registry Extension baseline of 46 seconds, too.

4th Test: 200 GPOs with one item vs one GPO with 200 items

This test is to show how performance can blow up if you take care of your GPO design. If we use 200 GPOs, this means the Registry Extension has to read 200 files (registry.xml) from the GPO Sysvol folder. If we put all these items into one single GPO, it has to read - guess what - only one single file.

This is what the one GPO I use now looks like. Remember these are the same 200 registry items with their 5 ILT filters for Battery as in test #3...

Now I ran GPUPDATE one more time and checked the results.

Ooops - processing time dropped down even below our baseline! That's because our baseline also had to process 200 files from sysvol, which is the real performance issue in this case. Reduce the number of GPOs to a reasonable minimum, and do not spread GPP settings over different GPOs - better use ILT.

For the registry thing above: You can create a collection (basically a kind of folder) that holds all your registry items. And you can do ILT for the whole collection, so you need to filter only once. This is the last timestamp for todays blog post.


Bingo - now we do filter only one time.


In this scenario with the given filter for a battery, there is almost no difference in performance between WMI filter and ILT. This might differ for other areas - and if it comes to Installed Software AKA Win32_Product / MSI Query, using ILT is an absolute must.

In the above scenario, we first had 200 WMI filters degrading performance by 27 Seconds. Then we had 200 ILTs with almost the same degradation. Only after putting all ILTs within one GPO, the baseline of 46 seconds vanished. And putting all items in a collection gave the ultimate performance gain. 

The real performance gains do not result from using different types of filtering, but from minimizing the number of filters and, much more, from minimizing the number of SYSVOl accesses. Each area within a GPO has its own settings file in SYSVOL, and all of these must be read to get applied. For ILT, they must even be read if they are not applied because the ILT resides in the same file. On the other hand, WMI filters reside in Active Directory, so they generally are read faster. But they only apply to GPOs as a whole.

My recommendation

Build huge GPOs that hold all settings that apply to almost anybody. Do not built individual GPOs to assign a printer or map a network share - put all of these in one GPO together, so you will have only one Printers.XML and only one DriveMaps.XML. Then use ILT.

Build small GPOs that target individual requirements. For these, use WMI filtering if you have an easy to use filter available. Test the performance of your filter before you deploy. If it's unacceptable, check whether ILT can help. This is especially true for registry items, which we can combine in a collection to minimize filtering.

This recommendation comes without warranties! :-)