Summary: Microsoft Scripting Guy, Ed Wilson, talks about using a filter hash table with Windows PowerShell to speed up boot trace parsing.
Hey, Scripting Guy! I don’t get it. You wrote a script yesterday, and said that the performance was bad. You suggested that you could improve the performance, but then you did not do anything about it. Why? Is it that the technique is too hard and you want to avoid work? This is disheartening to know if it is true. How about you throw us a bone so we can feed that dog of a script you wrote.
—AB
Hello AB,
Microsoft Scripting Guy, Ed Wilson, is here. Well, this morning I am sipping a cup of Darjeeling tea with a bit of lemon grass, crushed cinnamon stick, and a half spoonful of spearmint. The spearmint heightens the flavor, without overpowering it. The effect is quite soothing.
AB, I am sorry you feel like I am sloughing off by not improving the performance of my previous script. It worked for me, and that was my primary concern. In addition, I have written quite a bit about improving the performance of event trace queries. The best post is How to Improve the Performance of a PowerShell Event Log Query. To test the efficacy of my changes, I use the Test-TwoScripts.ps1 script that I talked about in How Can I Test the Efficacy of My Script Modifications?
Note This post is a continuation of Use PowerShell to Get Boot-Up Trace Events.
Using the FilterHashTable parameter
Sometimes, making a small change results in huge time savings. This script is an example. Using the FilterHashTable parameter is nearly always a good idea when it comes to filtering via the Get-WinEvent cmdlet. The key is a hash table—not surprising really. The hash table is used to filter—once again, no surprise.
A hash table has the “key = value” type of syntax. Therefore, the only thing that needs to be clarified is what can I use for a key? Luckily, these are well documented in the online Help for Get-WinEvent. Key pair values for the FilterHashTable parameter need to be one of the following:
Key |
Value Data Type |
LogName |
<String[]> |
ProviderName |
<String[]> |
Path |
<String[]> |
Keywords |
<Long[]> |
ID |
<Int32[]> |
Level |
<Int32[]> |
StartTime |
<DateTime> |
EndTime |
<DataTime> |
UserID |
<SID> |
Data |
<String[]> |
* |
<String[]> |
Using FilterHashTable for a filter
The first thing to keep in mind when using the FilterHashTable parameter for a filter is that when you use it, you must include the name of the log. This is because the parameter set that contains FilterHashTable does not also include LogName. The parameter set that includes LogName does not include the FilterHashTable parameter. These sets are shown here:
LogName:
Get-WinEvent [[-LogName] <String[]>] [-ComputerName <String>] [-Credential
<PSCredential>] [-FilterXPath <String>] [-Force [<SwitchParameter>]]
[-MaxEvents <Int64>] [-Oldest [<SwitchParameter>]] [<CommonParameters>]
FilterHashTable:
Get-WinEvent [-FilterHashtable] <Hashtable[]> [-ComputerName <String>]
[-Credential <PSCredential>] [-Force [<SwitchParameter>]] [-MaxEvents <Int64>]
[-Oldest [<SwitchParameter>]] [<CommonParameters>]
So by using the previous table, I can easily modify the Foreach portion of my script. Here is the original script:
Get-WinEvent -LogName $log.Logname -ea 0 |
where {$_.timecreated -gt $bootTime -and $_.timecreated -lt $bootTime.AddMinutes(5)}
Here is the modified script:
Get-WinEvent -ea 0 -filterHashTable @{
LogName = $log.Logname;
StartTime = $bootTime;
EndTime = $bootTime.AddMinutes(5)}
Not only does the script run a lot faster, but the FilterHashTable script is easier to read. Here is the complete, revised script:
$bootTime = (Get-CimInstance win32_Operatingsystem).lastbootuptime
“Boot time is $($bootTime)”
Foreach($log in Get-WinEvent -ListLog *)
{
“Events from $($log.Logname) event log”
Get-WinEvent -ea 0 -filterHashTable @{
LogName = $log.Logname;
StartTime = $bootTime;
EndTime = $bootTime.AddMinutes(5)}
}
Tracking the changes
So how did the changes do? Well, the original script took an average of 595 seconds to complete—that is nearly 10 minutes. The revised script took an average of 10 seconds to run!
And it did not take all that long to make the change. In fact, it took me less than three minutes to change it. The cool part is that the change took less than half the time it took for the script to run. Bottom line, do not be afraid of FilterHashTable. Use it all the time. Filter to the left of the pipeline, not to the right of the pipeline.
AB, that is all there is to using the FilterHashTable parameter to improve the performance of a Windows PowerShell event script. Join me tomorrow when I will talk about other cool Windows PowerShell stuff.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy
0 comments