I have seen a few interesting variations on using where-object during the games. This is normally aliased to where. You can use ? if you are fanatical about aliases but to me your PowerShell starts to become unreadable if its heavily aliased.
Consider get-process. It returns a set of process objects. Where-Object is used to put a filter on those objects to cut down the amount of data on the pipeline –
PS> get-process | where {$_.Handles -gt 500}
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
——- —— —– —– —– —— — ———–
558 9 1576 3424 46 384 csrss
660 11 1768 6816 102 452 csrss
1396 38 45412 58896 262 40.69 2776 explorer
622 23 43196 63204 309 30.76 2164 iexplore
1000 17 4988 10440 36 508 lsass
509 14 37992 43308 202 4.06 4688 powershell
938 35 42864 27516 131 3620 SearchIndexer
628 16 16392 15968 90 824 svchost
803 18 65548 73660 160 864 svchost
1369 34 22884 34012 200 900 svchost
504 17 6616 11640 52 1056 svchost
784 0 48 968 3 4 System
669 50 109832 78000 400 17.99 1700 WindowsLiveWriter
526 18 17084 24020 150 4.06 788 wlcomm
1951 178 222312 217488 689 96.39 3872 wlmail
or
PS> get-process | where {$_.CPU -gt 50}
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
——- —— —– —– —– —— — ———–
124 8 28828 24996 120 131.10 2744 dwm
485 23 14940 37444 202 52.49 3272 iexplore
363 26 25180 60088 335 78.14 5336 WINWORD
1951 178 222312 217488 689 96.42 3872 wlmail
We often need to combine filters. These can apply both filters or either filter.
Both filters are applied using the –and operator
PS> get-process | where {$_.CPU -gt 50 -and $_.Handles -gt 500 }
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
——- —— —– —– —– —— — ———–
1956 179 222332 217508 689 96.47 3872 wlmail
In the situation where you want either the CPU or the Handles filter to apply you use the –or operator
PS> get-process | where {$_.CPU -gt 50 -or $_.Handles -gt 500 }
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
——- —— —– —– —– —— — ———–
532 9 1576 3368 46 384 csrss
651 11 1768 6816 103 452 csrss
124 8 27804 23964 119 132.18 2744 dwm
1403 38 46744 60284 263 41.53 2776 explorer
619 23 43128 63196 308 30.76 2164 iexplore
488 23 14940 37444 202 52.51 3272 iexplore
992 17 4988 10440 36 508 lsass
566 14 34704 40004 202 4.68 4688 powershell
918 35 42860 27436 131 3620 SearchIndexer
617 16 16364 15952 89 824 svchost
807 18 65548 73684 160 864 svchost
1371 34 22932 34048 201 900 svchost
508 17 6616 11632 52 1056 svchost
782 0 48 968 3 4 System
672 50 103560 76708 400 32.85 1700 WindowsLiveWriter
363 26 25180 60088 335 78.16 5336 WINWORD
520 18 17060 24000 150 4.09 788 wlcomm
1953 178 222332 217508 689 96.52 3872 wlmail
Notice the very different outputs!
One thing I have seen in the games is the use of cascading where
PS> get-process | where {$_.CPU -gt 50 } | where {$_.Handles -gt 500 }
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
——- —— —– —– —– —— — ———–
1953 178 222312 217496 689 96.52 3872 wlmail
logically this is equivalent of where {$_.CPU -gt 50 -and $_.Handles -gt 500 }
Is there any difference in speed
1..100 | foreach {
Measure-Command -Expression {get-process |
where {$_.CPU -gt 50 -and $_.Handles -gt 500 }}
} | Measure-Object -Average TotalMilliseconds
produces an answer of 153.92904 milliseconds
1..100 |
foreach {Measure-Command -Expression {get-process |
where {$_.CPU -gt 50 } | where {$_.Handles -gt 500 }}} |
Measure-Object -Average TotalMilliseconds
gives 152.905894 milliseconds
Not a massive difference. But does the order of the where statements make a difference?
1..100 | foreach {
Measure-Command -Expression {get-process |
where {$_.Handles -gt 500 -and $_.CPU -gt 50 }}} |
Measure-Object -Average TotalMilliseconds
produces an answer of 51.495388
1..100 | foreach {
Measure-Command -Expression {get-process |
where {$_.Handles -gt 500 | where {$_.CPU -gt 50 } }}} |
Measure-Object -Average TotalMilliseconds
gives 37.23507 milliseconds
Filtering on Handles first produces a quicker result because it is a heavier filter – it produces less out put so the second filter has less work to do. I wasn’t expecting such a big difference between the use of –and & the cascading where statements though – that was a surprise.
So what have learnt:
- where filter clauses can be combined with –and OR –or
- where filter clauses can be cascaded in multiple where statements
- putting the heaviest filter first speeds the process
- cascading where statements can be quicker than using –and
Be careful with the last statement and test any code before committing to using cascading wheres Also test the order of your filters very carefully.