Advanced Performance

Optimize the performance of PowerCLI’s views

Until now, UpdateViewData() enabled you to update the whole view or specified view property. If you wanted to retrieve some nested view, you needed to call Get-View again. And if the view you needed was somewhere deeper in the hierarchy, you needed to call Get-View multiple times.

Let’s say for example that you have the VM folder view and you need the VM network of all your virtual machines. What you had to do until now is something like this:

    $vmViewList = Get-View $vmFolderView.ChildEntity | Where {$_ -is [VMWare.Vim.VirtualMachine]}
    $vmNetworkList = Get-View ($vmViewList | % {$_.Network})

Now you can do the same thing in significantly more convenient way:

    $vmFolderView.UpdateViewData(“[VirtualMachine]ChildEntity.Network.*”)

The above line updates the VM folder view in such way that it contains the desired VM network views. The property path parameter of UpdateViewData states that we request only the virtual machine child entities of the VM folder (VM folder may contain other nested folders) and for all those virtual machines we want their networks. When you browse the VM folder view after this call, you’ll notice that a new property has appeared – LinkedView. Inside this property you’ll see record for each nested view of the VM folder, but only the requested ChildEntity is populated – all virtual machines situated directly in the VM folder are available there. Each ChildEntity also contains LinkedView where only the virtual machine network is populated. In other words, the network of the first virtual machine can be accessed like this:

    $vmFolderView.LinkedView.ChildEntity[0].LinkedView.Network

So what is the big deal with this new feature?

The most obvious answer is that the code is much shorter and readable. The filtering of the folder child entities is specified in the property path parameter of UpdateViewData method, rather than performing it manually.

If you execute both commands against well loaded VC, you’ll also notice the difference in the execution time. Using Measure-Command on my environment with about 500 virtual machines I measured significant difference: about 300 milliseconds for the UpdateViewData call and about 30 seconds, using the multiple Get-View call approach.

There are some more things to mention:

When specifying property paths that include containers, which can hold more than one entity type, and require some property which does not belong to all supported entity types of this container, you should explicitly describe the type of the retrieved container entities. Otherwise you’ll get an error:

    $vmFolderView.UpdateViewData("ChildEntity.ChildEntity.*")
    Exception calling "UpdateViewData" with "1" argument(s): "The specified path is not correct. Element 'childEntity' doesn't exist."
    At line:1 char:19
    + $fv.UpdateViewData <<<< ("ChildEntity.ChildEntity.*")
        + CategoryInfo          : NotSpecified: (:) [],     MethodInvocationException
        + FullyQualifiedErrorId : DotNetMethodException

The reason for the error is that the child entity of the folder may be either another folder or virtual machine and the virtual machine does not have ChildEntity property.

There’s no problem to specify more than one property path, populating in such way the needed linked views with a single call:

    $vmFolderView.UpdateViewData(“[VirtualMachine]ChildEntity.Network.*”, "[Folder]ChildEntity.Name")

The same approach can be used directly with Get-View like this:

    $vmFolder | Get-View -Property "[VirtualMachine]ChildEntity.Network.*"