Some Windows PowerShell scripts can be useful but consume a great deal of memory, take a long time to complete, or both. Here are some tips on how to improve the performance of such scripts.
Optimize Last
Don't try to optimize PowerShell scripts as you write them. You might be optimizing code that either disappears on its own or doesn't have a significant effect on final performance. Scripter time is always more difficult to come by than CPU cycles.
Use Filtering Parameters
PowerShell can consume a lot of resources because some cmdlets are designed to provide immense quantities of data. So, if you're using a cmdlet that has filtering parameters (-Filter, -Include, and -Exclude), use them.
If a cmdlet supports the -Filter parameter, you want to use it first. It uses the underlying APIs for an object, which means the code is extremely fast because the filter is applied before the cmdlet creates the objects. The
-Include and -Exclude parameters are applied to objects after the cmdlet has already created the objects but before the objects go into the PowerShell pipeline. So, they're slower than -Filter, but they're still faster than filtering after the objects are in the PowerShell pipeline.
Sometimes you should use more than one type of filtering. For example, suppose you're searching for all files on the D drive with the file extension .htm. The -Filter parameter uses the traditional Windows file-system semantics, where *.htm returns all files whose extensions begin with .htm. The Windows APIs implement this filtering, making it extremely fast. There's an important limitation of the traditional APIs, however. They're very old and consequently just ignore anything in a file extension beyond the first three characters. So a search only for *.htm with -Filter would also return .html files, for instance. Therefore, for speedy filtering, you should use both -Filter (to cut out the vast bulk of files before loading them) and -Include (to get only .htm files). Here's what this code looks like
Get-ChildItem -Path D:\ -Filter *.htm -Include *.htm -Recurse
Remember, though, that -Filter uses the underlying APIs, so how fast it works depends on those APIs. Take, for example, the code
Get-WmiObject -Class Win32_Product `
-Filter 'Vendor LIKE "%Microsoft%"'
In this case, the -Filter argument works slower because the Get-WmiObject cmdlet uses the Windows Management Instrumentation (WMI) Scripting API. It's also slower because WMI uses the WMI Query Language (WQL) for filtering, so the filtering occurs within WMI.