giraffe-fsharp / Giraffe

A native functional ASP.NET Core web framework for F# developers.

Home Page:https://giraffe.wiki

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Returning streams, either with WriteStreamAsync or WriteFileStreamAsync or their handler equivalents, is extremely slow

reinux opened this issue · comments

With this code:

open System.Net.Http
open System.IO
open Giraffe
open Microsoft.AspNetCore.Builder
open Microsoft.Extensions.Hosting
open Microsoft.Extensions.Logging

let data =
  use client = new HttpClient()
  client.GetByteArrayAsync("https://apod.nasa.gov/apod/image/0704/carina_hst_big.jpg").Result

printfn $"Image length: %.2f{float data.Length/1024.} KB"

let webApp =
  choose [
     route "/test-bytes"    >=> warbler (fun _ -> setBody data)
     route "/test-stream"   >=> warbler (fun _ ->  streamData false (new MemoryStream(data)) None None)
  ]

let builder = WebApplication.CreateBuilder()
builder.Logging.AddFilter(fun _ -> true) |> ignore
builder.Services.AddGiraffe() |> ignore

let app = builder.Build()
app.UseGiraffe webApp

app.Run()

/test-bytes takes around 50ms, whereas /test-stream takes 500ms-750ms.

The image is around 2.6mb, and almost all the time is spent in receiving the response as opposed to waiting for the response to begin:

image

I tried turning ranged processing on and off, as well as Firefox, Brave, Chromium, curl and System.Net.Http.HttpClient.

Just a shot in the dark, but I wonder if the response stream buffer isn't optimal, and it's causing a lot of TCP round trips?

Okay, yeah, so changing the buffer size in WriteStreamToBodyAsync to 1MB kind of did the trick -- now it's down to 100ms or so, which suggests it's probably still doing 2 or 3 round trips as opposed to just one.

I'm not sure what the right value for this should be, though 64kb seems a bit small for modern times. HTTP3 would probably solve this issue, but the Linux community's support of libmsquic is unsurprisingly tepid.

Nice, thanks for commenting the workaround you found @reinux. Do you think we can close this issue now?

I'll close it now. Please open a new issue if you'd like to discuss more about this topic.

@64J0 Sorry about that, I missed the notification from your previous comment. I found an interesting article related to this topic, so I'll start a new issue.