Profiling PowerShell cmdlets with ANTS Performance Profiler

Following the early lead of Exchange Server 2007, Citrix’s XenDesktop SDK (which I was fortunate enough to work on), and now the Azure platform, PowerShell is being used more and more to provide the scriptable interface to proprietary systems.

At Red Gate I’m usually profiling cmdlets to test the profiler itself – PowerShell is a great test case – but we know some of our users are cmdlet authors who want to know whether their code is performing as well as it should. PowerShell provides a timing function called Measure-Command, and of course it’s possible to instrument a script manually with StopWatch objects, but developers need to dig into their C# code, not the PowerShell script which invokes it.

Because powershell.exe is itself a .NET application, ANTS Performance Profiler can handle this. Profile the PowerShell executable with the command line arguments configured to load your module and run the cmdlet.

Starting PowerShell is CPU intensive, so I’ve put a Read-Host (the equivalent of Console.ReadLine) in my script to separate this noise from the time period I’m interested in, and another one at the end to give me time to read any exception messages.


For this example, I’ve got a cmdlet that will return a collection containing the most popular forum posts from The Beerhouse MVC web application. It does this by connecting to the backend database and running a SQL query.


This is pretty naïve code, but it serves to illustrate what we can expect from cmdlet profiling. Here’s the screenshot from ANTS:


Because the assembly which defines my cmdlet has the PDB in the same directory, ANTS has picked up the path to the source code and highlighted methods with source in bold. I’ve selected the PopularPosts node, and ANTS shows the source code in the panel below. It’s also picked out my SQL statement, and tells me that it took 149ms to run. That’s not bad, but if I wanted better performance over multiple runs I should probably be caching the SQL Server connection.


APP 8 spoiler alert!

A new feature in APP8 is the ability to instrument outgoing HTTP requests, such as calls to web services. In my second example cmdlet, Get-RedGateWebpage, I download a web page to illustrate this.

As before, ANTS shows me how much time was spent in ProcessRecord, and attributes it to the ~400ms spent downloading the web page.