Pode
Pode copied to clipboard
A one second delay with each request
Describe the Bug
I grabbed a sample from the Getting started documentation
Start-PodeServer {
Add-PodeEndpoint -Address localhost -Port 8080 -Protocol Http
Add-PodeRoute -Method Get -Path '/' -ScriptBlock {
Write-PodeJsonResponse -Value @{ 'value' = 'Hello, world!' }
}
}
I started that and wrote a simple loop to test the server:
1..1000 | ForEach-Object {
"Calling $_"
Invoke-RestMethod "http://localhost:8080/"
}
Running the above takes around 1025 seconds. About one second for each call. I haven´t heard anyone complain about performance so it´s weird that I get the one second delay.
In fact I have written a massive modular API-server (on the same machine) where there is no such delay.
What have I done wrong?
Expected Behavior
~20ms response time
Platform
- OS: Microsoft Windows 10.0.17763 (Server 2019)
- Versions:
- Pode: 2.8.0
- PowerShell: 7.2.15
Hi @grtswt,
This is actually an issue with Invoke-RestMethod
and Invoke-WebRequest
. The setup within these functions before making the request is what adds the extra duration.
If you have curl installed you'll see the requests respond as expected. For me using curl, same example, takes ~20s
(Measure-Command {
foreach ($i in 1..1000) {
curl.exe http://localhost:8080 -s
}
}).TotalSeconds
Hey @Badgerati do you know if this issue is related to Windows? I am getting opposite results running PowerShell 7.3.6 on my Mac, interestingly, with IRM being quite a bit faster:
for i in {1..100}; do curl -s -w '%{time_total}
' -o /dev/null https://disease.sh/v2/states; done | awk '{sum+=$1} END {print sum/NR * 1000}'
482.664
(Measure-Command {
foreach ($i in 1..100) {
Invoke-RestMethod -Uri 'https://disease.sh/v2/states'
}
}).TotalMilliseconds / 100
390.635806
Potentially, I remember seeing reference to something about the 1s delay when PS7.3 was fixed, though I'm on 7.3.9 on Windows and I still get the delay! SO it might have only been fixed on Unix/Mac.
I had a quite look, it might have been this: https://github.com/PowerShell/PowerShell/pull/17896
I have done some further tests.
When using cURL: using localhost: ~300ms per call using 127.0.0.1: ~5,7ms per call
When using invoke-restmethod: using localhost: ~1025ms per call using 127.0.0.1: ~6,3ms per call
I think we can assume the added time when using hostname compared to IP-address is due to slowness in curl or Invoke-Webrequest.
Should we close the issue?
/Peter
I'll do a bit of testing, before we close the issue, just to confirm 100% that the latency different between localhost and 127.0.0.1 isn't due to Pode - as when a hostname is used Pode does have some extra logic it run.
The fact is 3x faster in curl though tells me it's likely just IRM/IWR, and those tools doing some DNS lookups.
Dear @grtswt, I found the root cause. Its Windows 10 .NET Core localhost IPv6 networking! Requests to localhost will first try to connect to [::1] (localhost on ipv6) rather than ipv4. To work around this, you need to change your PodeEndpoint to the IPv6 version of localhost like so:
# Add-PodeEndpoint -Address localhost -Port 8080 -Protocol Http
Add-PodeEndpoint -Address '[::1]' -Port 8080 -Protocol Http
And then BOOM, its all fast. As far as I can tell, there is no way currently in Pode to bind to both IPv4 and IPv6 for a single route or endpoint. @Badgerati, would you like me to open a separate feature request to support IPv4 and IPv6 on a single endpoint and route?
Further details: Markekraus comment led me down this path: https://github.com/PowerShell/PowerShell/issues/6199#issuecomment-366992148
To here: https://github.com/microsoft/WinAppDriver/issues/1269
And I see that Pode got IPv6 support as talked about in this Pode issue: https://github.com/Badgerati/Pode/issues/915
This was resolved by #1251, via the addition of a -DualMode
switch on Add-PodeEndpoint
to enable listening on both IPv4/6 at the same time, and will be in v2.10.0.