WireMock-Net / WireMock.Net

WireMock.Net is a flexible product for stubbing and mocking web HTTP responses using advanced request matching and response templating. Based on the functionality from http://WireMock.org, but extended with more functionality.
Apache License 2.0
1.41k stars 209 forks source link

Requests are very slow (~2.1 sec) - bad performance #554

Closed narcis-sy closed 3 years ago

narcis-sy commented 3 years ago

Describe the bug

Requests to the server are handled very slowly, ~2.1 sec for a simple get.

Expected behavior:

Given that the server is in memory I would expect a response time of less de 50ms.

Test to reproduce

Simple add a stopwatch in any of the tests in https://github.com/WireMock-Net/WireMock.Net/blob/master/test/WireMock.Net.Tests/WireMockServerTests.cs I only count the request time, not the actual start of the server.

   var s = Stopwatch.StartNew();
            // then
            Check.That(server.Mappings).IsEmpty();
            Check.ThatAsyncCode(() => new HttpClient().GetStringAsync("http://localhost:" + server.Ports[0] + path)).ThrowsAny();
            s.Stop();

This gives 2.1 sec. I've measured the WireMockMiddleware and it takes 62ms. So something is lost on the way.

Other related info

Using xunit for testing

narcis-sy commented 3 years ago

This may be something from my local machine. It seems the tests ran by the repos CI/CD run fast. I've tested it also on our CI/CD and they run fast. It's probably something on my machine, although I did disable every firewall, windows defender, everything.

kaiserbergin commented 3 years ago

@narcis-sy did you ever figure out your local issue? I realized I was running into a similar issue when I placed timeout policies on my http client requests and started seeing errors in testing.

narcis-sy commented 3 years ago

@kaiserbergin Nope :( I happens just locally and just for some people (Win10). I tried disabling firewall everything.. still takes time, idk why.

benagain commented 3 years ago

I am seeing the same problem - the first request to WireMock from a HttpClient takes ~2 seconds. Subsequent requests from the same HttpClient object are fast, but the first request from a new HttpClient again takes about 2 seconds. This adds up to a fairly dramatic time cost when running our entire test suite.

I am also on Win10, and am using .NetCore 3.1 and 5.0.

I went digging into it, and it turns out to be something to do with requesting "any" IP address when configuring Kestrel options in AspNetCoreSelfHost.NETStandard - at least in my scenario on Win10. That value IPAddress.Any actually means "any IPv4" address, and for some reason I haven't determined that is introducing the delay. If instead we tell Kestrel to use "any IPv4 or IPv6" address then the delay vanishes for me. The Kestel options has a handy ListenAnyIP method which will do this for us, and essentially uses an equivalent of IPAddress.IPv6Any.

Making that change reduces the execution time of any single WireMockServerTest from >2 seconds to 200-300ms.

Running the WireMock test suite itself is fairly dramatic. From:

dotnet test ./test/WireMock.Net.Tests/WireMock.Net.Tests.csproj --no-build --configuration Debug --framework netcoreapp3.1
...
Passed!  - Failed:     0, Passed:   784, Skipped:     8, Total:   792, Duration: *** 5 m 12 s ***

To:

dotnet test ./test/WireMock.Net.Tests/WireMock.Net.Tests.csproj --no-build --configuration Debug --framework netcoreapp3.1
...
Passed!  - Failed:     0, Passed:   784, Skipped:     8, Total:   792, Duration: *** 49 s ***

Note - those test times are misleading, they seem to be the cumulative count of all tests, even though the tests are running concurrently.

@StefH - I will create a PR for my fix to this and it would be great if you're happy to accept it. Please be aware that I am only able to test this on my Windows 10 machine. All of the various flavours do pass all their tests (net452 through netcore5.0) here, but I am not able to verify it on Mac/linux/elsewhere.