Get-CiVm CmdLet is much slower than the direct underlying REST calls

Using PowerCLI for fun and profit in general is a great thing to do – in general… However, in certain cases PowerCLIs implementation is much slower than using the underlying REST calls directly. This is especially true when using Get-CiVm to get information about a vCloud Director (vCD) virtual machine.

Consider the following fragment:

# connect to vCloud
PS > Connect-CiServer vCloud;
# get a list of all VMs
PS > $Vms = Search-Cloud –QueryType adminVM;
# grab first reported VM
PS > $VmSlim = $Vms[0];
PS > $VmSlim.id;
urn:vcloud:vm:deaddead-dead-dead-dead-deaddeaddead

This is all pretty fast, as we are using the Search-Cloud CmdLet, that utilises the vCD Query service.

Now we want to get a “full” VM object and call the Get-CIVM on the id/urn of the (or any) VM as the “slim” VM object returned by the Query service does not contain all properties of a VM:

PS > $Vm = Get-CIVM -id $VmSlim.id;

The interesting thing about this is: when you have a nice test environment with only a few machines it runs through quite quickly (around 300-400ms). But as soon as you have an environment with only a couple of hundred VMs things are getting considerably slower (talking seconds):

PS > Measure-Command { $Vm = Get-CIVM -id $VmSlim.id; }
Days : 0
Hours : 0
Minutes : 0
Seconds : 1
Milliseconds : 738
Ticks : 17386313
TotalDays : 2.01230474537037E-05
TotalHours : 0.000482953138888889
TotalMinutes : 0.0289771883333333
TotalSeconds : 1.7386313
TotalMilliseconds : 1738.6313

When checking the REST log in “/opt/vmware/vcloud-director/logs/” you will notice the call of GetCiVm generated these two calls:

GET /api/entity/urn:vcloud:vm:deaddead-dead-dead-dead-deaddeaddead
GET /api/query?type=adminVM&format=records&filter=name==vmname&sortAsc=name&pageSize=128

And before you start blaming your environment, database server or whatever, try to execute these REST calls directly via a WebClient object with the same session as described in my post about reusing vCD session cookies:

Measure-Command {
$wc.Headers.Add("Accept", $HeaderAcceptValue);
$wc.Headers.Add("Cookie", $HeaderCookieValue);
$Data = $wc.DownloadString("https://vcloud/api/entity/urn:vcloud:vm:deaddead-dead-dead-dead-deaddeaddead ");
$Data
$wc.Headers.Add("Accept", $HeaderAcceptValue);
$wc.Headers.Add("Cookie", $HeaderCookieValue);
$Data = $wc.DownloadString("https://vcloud/api/query?type=adminVM&format=records&filter=name==vmname&sortAsc=name&pageSize=128");
$Data
}

And voilà: times range from 115ms to 450ms (regardless of cached or uncached objects) making the direct REST calls a factor between 3 to 10 tims faster!

The question still to be answered is: where does the PowerCLI spend all of its time and lose its speed?

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

%d bloggers like this: