Pode icon indicating copy to clipboard operation
Pode copied to clipboard

A one second delay with each request

Open grtswt opened this issue 1 year ago • 5 comments

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

grtswt avatar Oct 30 '23 12:10 grtswt

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

Badgerati avatar Oct 30 '23 21:10 Badgerati

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

fatherofinvention avatar Nov 04 '23 15:11 fatherofinvention

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

Badgerati avatar Nov 05 '23 23:11 Badgerati

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

grtswt avatar Nov 06 '23 10:11 grtswt

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.

Badgerati avatar Nov 09 '23 08:11 Badgerati

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?

Szeraax avatar Mar 02 '24 04:03 Szeraax

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

Szeraax avatar Mar 02 '24 04:03 Szeraax

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.

Badgerati avatar Apr 14 '24 09:04 Badgerati