Ironman Software Forums
Continue the conversion on the Ironman Software forums. Chat with over 1000 users about PowerShell, PowerShell Universal, and PowerShell Pro Tools.
PowerShell Universal allows for users to create APIs using PowerShell. These APIs can be used to create webhooks, integrate with other systems or provide a REST API for your PowerShell scripts. In this post, we’ll look at some improvements you can make to improve API performance.
In this post, we’ve used West Wind WebSurge to test API performance. This tool allows you to send a number of requests to a URL and measure the performance of the requests. We are running a 60 second test with 10 threads.
For this test, we are running an unlicensed version of PowerShell Universal with a single API endpoint. The API endpoint is a simple script that returns a string.
New-PSUEndpoint -Url "/hello" -Method @('GET') -Endpoint {
"hello"
}
We are using LiteDB for persistence.
The first thing you can do is update to PowerShell Universal 4.1.5 or later. This version includes a number of performance improvements to the API system. We see about a 300% improvement in API performance with this release with default settings.
By default, PowerShell Universal has verbose logs configured. We will make the following changes to the logging configuration.
In appsettings.json
, set the SystemLogLevel to Error
rather than verbose.
{
"SystemLogPath": "%ProgramData%\\PowerShellUniversal\\systemLog.txt",
"SystemLogLevel": "Error"
}
Rather than sending log messages to the database and file system, we will disable user scope logging for APIs. You can send log messages for specific features, such as Apps.
New-PSULoggingTarget -Type "Database" -Properties @{
} -Feature "App"
New-PSULoggingTarget -Type "File" -Properties @{
path = "C:\ProgramData\PowerShellUniversal\log.txt"
} -Feature "App"
It’s also possible to reduce the log level for targets rather than disable them completely.
New-PSULoggingTarget -Type "Database" -Properties @{
} -Level "Error"
New-PSULoggingTarget -Type "File" -Properties @{
path = "C:\ProgramData\PowerShellUniversal\log.txt"
} -Level "Error"
Certain features of PowerShell Universal environments can impact performance. We will make the following changes to the environment settings.
Resetting the runspace state takes time so avoiding this can improve performance. Note that persistent runspaces keep the value of variables, functions and aliases defined within the execution of the endpoint. Depending on the implementation of your endpoint, this may not be desirable.
By default, PowerShell Universal will create 25 runspaces per environment. We will increase this to 100. This will increase memory usage but will slightly improve performance.
New-PSUEnvironment -Name "Integrated" -Version "7.3.6" -Path "Universal.Server" -Variables @('*') -PersistentRunspace -MaxRunspaces 100 -Description "An environment for running scripts directly in the PowerShell Universal server."
Above, you may notice that we are using the Integrated
environment. This is an environment that is built into PowerShell Universal. It is a PowerShell environment that runs directly in the PowerShell Universal process. Even if we were to adjust the endpoints to use an external environment, the results are similar. This is running within a PowerShell 7.3.7 environment.
SQL persistence can greatly improve API throughput. This test was performed against a local SQL database with all the above settings configured and only run on version 4.1.5.
With these changes, we’ve improved the performance of our API by ~1,900%. We’ve gone from 150 requests a second to 3,000 requests a second. Using SQL persistence had the greatest increase on performance. Particularly combined with changes to the logging system, you can achieve a significant increase in performance.
Continue the conversion on the Ironman Software forums. Chat with over 1000 users about PowerShell, PowerShell Universal, and PowerShell Pro Tools.
Receive once-a-month updates about Ironman Software. You'll learn about our product updates and blogs related to PowerShell.