Getting serious about performance in PowerShell.

I've spend a lot of time in the past looking at the performance of PowerShell but have never gotten around to blogging about it. However it has become quite a hot button among MVPs and others in recent days and we've been busy testing and comparing the speeds different techniques in PowerShell in both V1 and V2.

In V1 there seems to be extreme slowdowns when invoking cmdlet, functions, any type of scriptblock and when using the pipeline. If you write a one liner that is easy to read, very elegant, but uses a lot of "powershelly" techniques its performance is often terrible, compared to it you write it out as a longer script using more traditional imperative style with "C"ish loops as the like. This brings up the whole concept of what is cheaper and more valuable - CPU cycles that keep getting cheaper, or human time in writing and maintaining code - dynamic languages and especially shells will definitely answer that programmer productivity is more valuable, and thus performance can come second.(read about it in the context of python here.) However 59 millisecond average to call an empty powershell function on a dual core machine is pushing this truth to an absurdity. PowerShell should as a language should NOT be slower than BASIC on my Commodore-64 - an 1MHZ 8 bit machine.

Here is some background of where we are coming from. Brandon Shell Started it all here. And after we spend hours running tests and bantering about the subject on the #powershell IRC room on freenode, Mow covered some cool stuff here.

Basically the results of my tests showed that new-object is very slow in V1, but calling any CMDLET, even a simple C# cmdlet with one line of code is extremely slow, and about 30 to 50 times slower than calling that SAME  line of code from powershell as a static method on a C# assembly. Additionally if you take that 50 times faster static method call, and wrap in it a simple powershell function, you loose all your spend gains and its even slower than calling the new-object CmdLet.

The great thing from Mows tests is that in V2 it seems that on the language side of things, scriptblocks,functions and the pipelines have spend up drastically (in the magnitude of about 2000% to 3000%. And cmdlet invocation has spend up also, but is about 6 times slower than just calling C# static methods. GO V2 GO V2 , but is it enough?

Given that V1 is going to be important for a long time, I think that powershell scripters need to still try to script in a "PowerShelly" way, but when they determine that something really has to be performant , they need to know what workarounds they can do in PowerShell to speed things up, understanding where the bottlenecks in PowerShell are.

But this post isn't about those performance solutions - I'm sure that we will cover a lot of them over the coming of the months. I want to RANT.

One of the reasons I think PowerShell has so many language quirks (and thus related gotchas when learning to do advanced stuff and solving bugs) is because it is Defined by Implementation instead of being Defined by Specification. To be honest, PowerShell is more of a platform , than a language or even a shell, and as it brings some new ideas and melds existing ideas in totally new ways, almost experimental ways, I don't think it could have been defined any other way. However its quirks and yes also its performance is a result of that. I believe it needs to be reviewed by traditional language designers and not be excused "because its a shell language". I believe that the importance of PowerShell is growing phenomenally and being part of Microsoft's common engineering requirement I strongly believe such close working with the CLR team should be done, and even if PowerShell is defined by Implementation and will likely be in version 2 also - SPEND THE TIME TO AT LEAST DEFINE THE SPECIFICATION, DOCUMENT THE INTENDED (and thus real) BEHAVIOUR, RELEASE A FULL GRAMMAR, RELEASE OFFICIAL XSD SCHEMAS of the XML ELEMENTS, and if specification is what defines it, and that specification is best represented in the automated unit tests - maybe , just maybe even release such tests  , as per other dynamic languages. I think some of this stuff should at least be done BEFORE V2 is released. I mean getting a V2 and not even having a V1 grammar. </end of rant>


Despite the above concerns, I love PowerShell, and the general performance doesn't bother me. Being able to code at the speed of thought, and do things with far less code than C#, and do things interactively and dynamically totally win out. PowerShell does introduce many new tangents on concepts and mash together some amazing things, its amazing they got it as right as they did the first time. I know if I had implemented such a platform/language it would be less consistent and probably slower than a ZX81. PowerShell V2, even though only in CTP2 already shows great performance enhancements.

If that disclaimer gave you the warm fuzzies, don't get too comfortable, i have another pet peeve to blog about, and that is the fallacy called "Restricted Runspaces" and how the lack of being able to truly sandbox PowerShell has me running in the direction of IronRuby - But that's for another day.

-Karl / Shell Tools

Posted Jun 12 2008, 09:12 PM by Karl Prosser
Copyright 2012 All rights reserved.