diff --git a/src/FSharp.Data.Http/Http.fs b/src/FSharp.Data.Http/Http.fs index e394ad507..d34cc9514 100644 --- a/src/FSharp.Data.Http/Http.fs +++ b/src/FSharp.Data.Http/Http.fs @@ -2043,6 +2043,12 @@ type Http private () = req.AutomaticDecompression <- DecompressionMethods.GZip ||| DecompressionMethods.Deflate + // Optimize HTTP performance with connection keep-alive and pooling + req.KeepAlive <- true + req.ServicePoint.UseNagleAlgorithm <- false // Disable Nagle for better latency + req.ServicePoint.Expect100Continue <- false // Reduce handshake overhead + req.ServicePoint.ConnectionLimit <- 10 // Allow more concurrent connections per endpoint + // set cookies let addCookiesFromHeadersToCookieContainer, cookieContainer = match cookieContainer with diff --git a/tests/FSharp.Data.Benchmarks/FSharp.Data.Benchmarks.fsproj b/tests/FSharp.Data.Benchmarks/FSharp.Data.Benchmarks.fsproj index 57119c667..f1ddf1c93 100644 --- a/tests/FSharp.Data.Benchmarks/FSharp.Data.Benchmarks.fsproj +++ b/tests/FSharp.Data.Benchmarks/FSharp.Data.Benchmarks.fsproj @@ -14,6 +14,7 @@ PreserveNewest + diff --git a/tests/FSharp.Data.Benchmarks/HttpBenchmarks.fs b/tests/FSharp.Data.Benchmarks/HttpBenchmarks.fs new file mode 100644 index 000000000..2396da47e --- /dev/null +++ b/tests/FSharp.Data.Benchmarks/HttpBenchmarks.fs @@ -0,0 +1,76 @@ +namespace FSharp.Data.Benchmarks + +open System +open System.Net +open BenchmarkDotNet.Attributes +open FSharp.Data + +[] +[] +type HttpBenchmarks() = + + // Use public HTTP test endpoints for realistic benchmarks + let httpBinUrl = "https://httpbin.org" + let smallEndpoint = $"{httpBinUrl}/get" + let jsonEndpoint = $"{httpBinUrl}/json" + + [] + member _.SingleHttpBinRequest() = + try + Http.RequestString(smallEndpoint, timeout = 5000) + with + | :? WebException -> "Network error" // Handle network issues in CI + + [] + member _.HttpBinJsonRequest() = + try + Http.RequestString(jsonEndpoint, timeout = 5000) + with + | :? WebException -> "Network error" // Handle network issues in CI + + [] + member _.MultipleSequentialRequests() = + for _ in 1..3 do + try + Http.RequestString(smallEndpoint, timeout = 5000) |> ignore + with + | :? WebException -> () // Handle network issues in CI + + [] + member _.PostRequest() = + let body = TextRequest "test data" + try + Http.RequestString($"{httpBinUrl}/post", httpMethod = "POST", body = body, timeout = 5000) + with + | :? WebException -> "Network error" // Handle network issues in CI + + [] + member _.RequestWithHeaders() = + let headers = [("User-Agent", "FSharp.Data.Benchmarks"); ("Accept", "application/json")] + try + Http.RequestString(smallEndpoint, headers = headers, timeout = 5000) + with + | :? WebException -> "Network error" // Handle network issues in CI + + [] + member _.TypeProviderWorkloadSimulation() = + // Simulate a type provider fetching sample data and caching + for _ in 1..2 do + try + Http.RequestString(jsonEndpoint, timeout = 5000) |> ignore + with + | :? WebException -> () // Handle network issues in CI + + [] + member _.MultipleConnectionsToSameHost() = + // Test connection reuse with keep-alive optimization + let endpoints = [ + $"{httpBinUrl}/get" + $"{httpBinUrl}/json" + $"{httpBinUrl}/user-agent" + ] + for endpoint in endpoints do + try + Http.RequestString(endpoint, timeout = 5000) |> ignore + with + | :? WebException -> () // Handle network issues in CI \ No newline at end of file diff --git a/tests/FSharp.Data.Benchmarks/Program.fs b/tests/FSharp.Data.Benchmarks/Program.fs index 49be49dc0..e94066026 100644 --- a/tests/FSharp.Data.Benchmarks/Program.fs +++ b/tests/FSharp.Data.Benchmarks/Program.fs @@ -10,9 +10,11 @@ let main args = match args with | [| "json" |] -> BenchmarkRunner.Run() |> ignore | [| "conversions" |] -> BenchmarkRunner.Run() |> ignore + | [| "http" |] -> BenchmarkRunner.Run() |> ignore | _ -> printfn "Running all benchmarks..." BenchmarkRunner.Run() |> ignore BenchmarkRunner.Run() |> ignore + BenchmarkRunner.Run() |> ignore 0 \ No newline at end of file