Performance Footprint of PowerShell Logon Scripts
PowerShell is a popular and extremely versatile tool, but is it a good idea to use PowerShell in logon scripts? Let’s try to find out!
Setting the Stage
I am going to compare the resource utilization of the following languages frequently used with logon scripts:
How do you find the logon script’s duration and resource footprint? Such data is normally not too easy to come by, but uberAgent easily makes these and other logon metrics readily available.
All tests were performed on a virtual Windows Server 2012 R2, fully patched as of May 2015. Additional software: Citrix XenApp 7.6 VDA and uberAgent. The VM was equipped with 1 vCPU.
All measurements were taken in steady state, i.e. the machine had been booted up well in advance and I ignored the first logon because that basically puts all executables and DLLs from disk into RAM. During subsequent logons the disk is not used very much any more since all required files can be found in the operating system’s file system cache in RAM.
I was interested in language overhead. That is why I was testing with very simple scripts that write the username to a text file.
Writing the username to a file is a one-liner in batch:
echo %username% > %temp%\username.txt
It is a one-liner in PowerShell, too:
$env:username > $env:temp\username2.txt
VBScript requires an entire program to be written to accomplish the same task:
Set wshShell = CreateObject( "WScript.Shell" ) username = wshShell.ExpandEnvironmentStrings("%username%") outFileName = wshShell.ExpandEnvironmentStrings("%temp%") & "\usernamevbs.txt" Set outFile = CreateObject("Scripting.FileSystemObject").OpenTextFile(outFileName,2,true) outFile.WriteLine(username) outFile.Close
The batch file and the VBScript are in the 0.3 to 0.4 second range, whereas the PowerShell script takes a whopping 4.5 seconds to execute. Factor batch – PowerShell: 16x.
The batch file and the VBScript are in the 60 to 80 CPU ms range, whereas the PowerShell script consumes 1,123 CPU ms. Factor VBScript – PowerShell: 18x.
The batch file and the VBScript are in the 20 to 24 MB range, whereas the PowerShell script needs 98 MB RAM. Factor batch – PowerShell: 5x.
The total duration of the user logon is important to good user experience. With Citrix XenApp published applications logon speed even is critical. Logon script performance is often underestimated, partly due to the fact that Windows does not tell you how long a logon script took to execute and what the resource footprint was. uberAgent adds much needed visibility by providing detailed information about all aspects of the user logon.
PowerShell is a great tool, but its resource footprint and runtime overhead make it a difficult recommendation for logon scripts which run at a point in time where many processes are competing for resources. Logon delays badly affect user experience. Any tools added to this phase should be as efficient as possible.
Ouch – which versions of Windows Management Framework and Windows were these tests run under?
The tests were run on a fully patched (as of May 2015) Server 2012 R2.
Wow – totally the opposite of what I would have expected. Back to batch it is!
Kind of expected, isn’t it? SetACL Studio should also be rewritten in C++ in my opinion.
I won’t argue over PowerShell’s resource requirements, however apart from that the other important statement you made is: “VBScript requires an entire program to be written to accomplish the same task”. Compare PowerShell’s possibilities and maintainability against maintaining pages of VB Scripts or batch files (KiXtart anyone?) and the (hidden) costs. Hardware is cheap.
I think you are jumping to conclusions a bit here. One command does not a script make!
I guess a large part of the time you are measuring is loading of Powershell itself. Once it is loaded it could be a lot faster actually executing commands, so if you have a couple of pages of logon script it could be kicking Batch backside. Honestly I don’t think it will but I would surprised if the difference between Batch and PS is not a lot smaller with a large script. The strength of Batch is small footprint, fast loading and execution. Powershell has a lot more functionality but that results in a larger executable (+ dependencies) to be loaded into RAM, thus the longer loading time. Different horses etc.
And 4.5 seconds? I’m sure it’s a test environment you are testing on but I just ran your script on my laptop, and it can’t have taken more than two seconds (no UberAgent here for exact timing, sorry mate). The actual command execution took 39 ms. If I put the same command in the script three times, the second and third time the command is executed takes only 3 ms.
But all my bitching aside, logon scripts are so last century anwyay :-)
Me again : )
Do you know whether the ngen scheduled tasks had run prior to these logons? Micah Rairdon mentioned this: https://social.technet.microsoft.com/Forums/windows/en-US/c777c2dc-0014-4ec6-b2ba-9711121f63d5/powershell-slow-to-start-on-clean-install-with-empty-profile-present?forum=w8itprogeneral
No, I don’t.
could you be so kind as to re-evaluate your findings with an up-to-date version of powershell and Server 2016/Windows 10?
I would really like to know if anything has improved performance wise lately.
I have a whole bunch of ps scrpts around. Is there any program/app that converts your ps scripts to batch automatically?
It’s highly unlikely such it’s even possible to convert PowerShell scripts to batch files.