Optimising WMI calls–part 1

Recently saw some code where user was running this

$bootupMemory = gwmi -Query “SELECT * FROM Win32_OperatingSystem” -ComputerName $srv
$cpuLoad = gwmi -Query “SELECT * FROM Win32_Processor” -ComputerName $srv

$tSessions = gwmi -Query “SELECT * FROM Win32_TerminalService” -ComputerName $srv

$ima = gwmi -Query “SELECT * FROM Win32_Service WHERE name=’imaservice'” -ComputerName $srv
$mfcom = gwmi -Query “SELECT * FROM Win32_Service WHERE name=’mfcom'” -ComputerName $srv
$ctxPrintMgr = gwmi -Query “SELECT * FROM Win32_Service WHERE name=’cpsvc'” -ComputerName $srv
$msmqstatus = gwmi -Query “SELECT * FROM Win32_Service WHERE name=’msmq'” -ComputerName $srv

$cDrive = gwmi -Query “SELECT * FROM Win32_Logicaldisk WHERE deviceid=’c:'” -ComputerName $srv
$dDrive = gwmi -Query “SELECT * FROM Win32_Logicaldisk WHERE deviceid=’d:'” -ComputerName $srv

against 300 machines.  There were some more calls they involved WMI classes installed by Citrix which I don’t use in my lab

Question was why was it running slow

Two thoughts initially are that repeated calls to Get-WmiObject involve creating, using and removing DCOM connections. This assumes that DCOM isn’t blocked by a firewall or the network. Using a single CIM session should speed up the process.

Secondly making multiple calls to the same class is inefficient.

In addition using the WQL query involves more typing which makes things more difficult to maintain.

Last point is that everyone knows how much I love aliases so you won’t be surprised if I point out that using them is BAD

I don’t have 300 servers in my lab – though using nano server VMs on a machine with 64GB ram you could do that – so I used some PowerShell looping to get round that

Measure-Command -Expression {

$srvs = ‘W16TP5TGT01’, ‘W16TP5TGT02’

for ($i=1; $i -le 150; $i++){

foreach ($srv in $srvs) {
$bootupMemory = gwmi -Query “SELECT * FROM Win32_OperatingSystem” -ComputerName $srv
$cpuLoad = gwmi -Query “SELECT * FROM Win32_Processor” -ComputerName $srv

$tSessions = gwmi -Query “SELECT * FROM Win32_TerminalService” -ComputerName $srv

$ima = gwmi -Query “SELECT * FROM Win32_Service WHERE name=’imaservice'” -ComputerName $srv
$mfcom = gwmi -Query “SELECT * FROM Win32_Service WHERE name=’mfcom'” -ComputerName $srv
$ctxPrintMgr = gwmi -Query “SELECT * FROM Win32_Service WHERE name=’cpsvc'” -ComputerName $srv
$msmqstatus = gwmi -Query “SELECT * FROM Win32_Service WHERE name=’msmq'” -ComputerName $srv

$cDrive = gwmi -Query “SELECT * FROM Win32_Logicaldisk WHERE deviceid=’c:'” -ComputerName $srv
$dDrive = gwmi -Query “SELECT * FROM Win32_Logicaldisk WHERE deviceid=’d:'” -ComputerName $srv
}
}
}

Measure command will run the commands but it reports the time taken rather than the results

I have 2 servers and loop 150 times round connecting to them and getting the results

Some caching of connectivity information occurs but this is close enough

Days              : 0
Hours             : 0
Minutes           : 8
Seconds           : 59
Milliseconds      : 419
Ticks             : 5394194858
TotalDays         : 0.00624328108564815
TotalHours        : 0.149838746055556
TotalMinutes      : 8.99032476333333
TotalSeconds      : 539.4194858
TotalMilliseconds : 539419.4858

A time of just under 9 minutes isn’t bad. This is fast enough to run during the day and can definitely be run over night

But we should be able to do better than that

Lets use a CIM session instead of individual DCOM sessions

Measure-Command -Expression {

$srvs = ‘W16TP5TGT01’, ‘W16TP5TGT02’

for ($i=1; $i -le 150; $i++){

foreach ($srv in $srvs) {
$cs = New-CimSession -ComputerName $srv
$bootupMemory = Get-CimInstance -Query “SELECT * FROM Win32_OperatingSystem” -CimSession $cs
$cpuLoad = Get-CimInstance -Query “SELECT * FROM Win32_Processor” -CimSession $cs

$tSessions = Get-CimInstance -Query “SELECT * FROM Win32_TerminalService” -CimSession $cs

$ima = Get-CimInstance -Query “SELECT * FROM Win32_Service WHERE name=’imaservice'” -CimSession $cs
$mfcom = Get-CimInstance -Query “SELECT * FROM Win32_Service WHERE name=’mfcom'” -CimSession $cs
$ctxPrintMgr = Get-CimInstance -Query “SELECT * FROM Win32_Service WHERE name=’cpsvc'” -CimSession $cs
$msmqstatus = Get-CimInstance -Query “SELECT * FROM Win32_Service WHERE name=’msmq'” -CimSession $cs

$cDrive = Get-CimInstance -Query “SELECT * FROM Win32_Logicaldisk WHERE deviceid=’c:'” -CimSession $cs
$dDrive = Get-CimInstance -Query “SELECT * FROM Win32_Logicaldisk WHERE deviceid=’d:'” -CimSession $cs
Remove-CimSession -CimSession $cs
}
}
}

Time is now

Days              : 0
Hours             : 0
Minutes           : 8
Seconds           : 31
Milliseconds      : 839
Ticks             : 5118397269
TotalDays         : 0.00592407091319444
TotalHours        : 0.142177701916667
TotalMinutes      : 8.530662115
TotalSeconds      : 511.8397269
TotalMilliseconds : 511839.7269

That’s a 5% speed increase for minimal coding effort

Next step is to remove the redundant WMI calls which we’ll do in the next post

This entry was posted in PowerShell and CIM, PowerShell and WMI. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s