TL;DR: In WMI filters, always select the key property of the class you are querying instead of 'SELECT * FROM'. This can reduce evaluation time by up to 90 percent!
If you use WMI filters, you should care about performance. Each filter in fact does need some time to be evaluated, and to verify this, we can easily use PoSh with its Measure-Command and Get-WmiObject cmdlets. In my previous post about WMI filters I'm targeting for OS versions. Let's verify one of these filters and its performance. To minimize noise, I crafted a 1000x loop around Get-WmiObject.
As we see, this filter takes about 23 ms average to evaluate. That's not a great issue, but if we use a lot of WMI filters, it can degrade performance notably.
So far, this is not a new thing. But why I'm writing this post at all? I recently came across this post on WindowsNetworking.com that states: Do not use the * wildcard selector, but instead use selected properties. What that means in the above query: Replace * with BuildNumber. Let's see how it performs after this small change.
Notably, execution time went down from 23 ms to 15 ms!
Select all properties: 23 ms
Select named property: 15 ms (-35%)
I was so excited about this 35% performance gain that I repeated this test with a lot of different classes and properties, and I also replaced the selected property with different other properties. One test was with a filter we use to target laptops:
select * from Win32_Battery
Let's verify how this one performs with the wildcard selection and with a distinct property.
This filter has no performance gain. Why? Because my test computer does not have a battery - the filter doesn't return any instances, so we cannot select any properties. But let's check another class - Win32_Service. I chose to filter for Name='winmgmt'.
Wow - things get weird! A dropdown from 118 ms to 15 ms, just by selecting a property instead of everything! This was so astonishing that I immediately repeated this test. This time, I chose to add a third query which selects DisplayName instead of Name.
The first two runs are almost identical to the above ones: 119 ms compared to 16 ms. The third run takes 103 ms which is quite slow. Seems logical - we are targeting Name='winmgmt', so WMI must have read the Name property already. In addition, Name is the key property of Win32_Service.
Select all properties: 119 ms
Select named property: 103 ms (-13%)
Select key property: 16 ms (-87%)
I verified the influence of the key property through a test with the following query:
SELECT DisplayName FROM Win32_Service WHERE DisplayName = 'Server'
This query took almost exactly the same amount of time as
SELECT DisplayName FROM Win32_Service WHERE Name = 'Server'
As soon as I do not select Name, but any other property, it takes about 100 ms instead of about 15 ms, regardless of the property I'm filtering for.
To finally proof the key property influence, the following test was done without selecting a distinct service, but simply all services. Again, one query selects *, one query selects Name and one query selects DisplayName.
The first query - not surprising - takes 126 ms which is almost equal to the above one. The second and third query clearly proof that selecting the key property of a class can improve query speed by about 50%.
Select all properties: 126 ms
Select named property: 106 ms (-16%)
Select key property: 47 ms (-63%)
To cross verify this for other classes, I did tests with Win32_CodecFile and with Win32_Environment (both have the key property Name).
With Win32_CodecFile, we see no difference. But that's ok - still selecting a distinct property instead of * is better, because performance at least doesn't degrade if we do so :-)
With Win32_Environment, we see little differences, but we see them. And they again proof that it is better to select any property instead of just '*', and that it is better to select the key property than any other one.
Select all properties: 23,6 ms
Select named property: 21,0 ms (-11%)
Select key property: 20,4 ms (-14%)
That's it for now, happy fast filtering :-)