New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Performance difference when using ResponseBuffering middleware #3100
Comments
Any latency metrics? |
I can add a scenario for this piece of middleware and come back with more stats. |
I couldn't remember there being much difference in the latency, but i went back to check it and here are the figures, i haven't included the latency for the 730 byte payload: Latency tests returning a 10KB JSON payload:
Using the ResponseBuffering middleware:
Latency tests returning a 100KB JSON payload:
Using the ResponseBuffering middleware:
Latency tests returning a 1MB JSON payload:
Using the ResponseBuffering middleware:
Latency tests returning a 10MB JSON payload:
Using the ResponseBuffering middleware:
As you can see, any difference in latency for the most common use cases (up to 100KB payloads) is insignificant in comparison to the latency of even the fastest broadband connections. Again, as in the throughput test results, its only on the 1MB payload where the results are notably better for the default config, i am not sure why that isn't the case for the 10MB payload as well. I plan to test this over a network link from a linux server to a client, but a quick test from another machine to my Macbook showed very similar results in terms of the differences in throughput, but the throughput was less overall. So far from this limited test, it seems that the only benefit of the default configuration without Response Buffering is for 1MB payloads, which i think is a rare and generally unwise use case. If further tests confirm this, it would make sense that Response Buffering should be enabled by default to suit the vast majority of use cases and provide much better error handling. I can see the the response is delivered differently when not using Response Buffering as the time-to-first-byte for the 1MB example is 0ms and the complete request takes 33ms, showing that the chunked response transfer is working. When using Response Buffering the time-to-first-byte is 33ms and the request takes 33ms. This suggests that slower transfer speeds are required to see the benefits for the chunked response transfer. It would be interesting to see how different network link speeds affect the throughput and latency for the 2 configurations. |
I made a custom app there: https://github.com/aspnet/BasicMiddleware/tree/sebros/benchmarkapps/benchmarkapps/BufferingBenchmarks Using our performance infrastructure, all combinations have better RPS and latency with non-buffered results. This is not a universal conclusion as this is only measuring a sample Github Json payload (more realistic). I also confirmed that MVC Views are already buffered so they should not be impacted and hence I didn't measure them. Physical - Linux
Physical - Windows
Cloud - Linux
Cloud - Windows
|
I haven't ran your app yet, what was the size of the JSON response being measured? Can you run this test for the response sizes that i have tested so see what you get? Even for this example, for myself personally, there is not enough benefit to outweigh the significant disadvantages of NonBuffered. The differences are all less than about 6% Ill try my next set of tests as soon as i get chance before i make a final decision. I might even compare it to Node Express.... as like for like as possible of course. |
I used this as an example: https://developer.github.com/v3/users/#get-the-authenticated-user Feel free to add more scenarios to my app, even on your fork, I can run automated tests on anything that is in Github if it follows this app template. Also, I am testing using the dev branch of all aspnet, i.e.e 2.1, and not 2.0. |
Closing because no further action is planned for this issue. |
The default configuration of a new .Net Core project does not use Reponse Buffering, instead the response is sent in chunks so that the result payload can start to be sent while it is being serialized which is supposed to improve memory usage and performance. This is a new feature in .NET Core, in my initial testing when coming from the previous generation of .NET i was not aware of this new feature that was enabled by default.
I have done some basic testing to help decide whether it is worth sticking with the default or using the ResponseBuffering middleware which in theory would slow things down and consume more server RAM.
The tests where run from a .Net Core 2 Web API using an in memory data repository. The throughput tests where ran for 10 seconds several times over to obtain an average result. The payload size is the total size including the headers. The memory usage was monitored during a 60 second throughput test. (observing the 3 dotnet processes found).
Everything was performed locally on a Macbook Pro with 16GB RAM.
Throughput tests returning a 730 Byte JSON payload:
Default configuration (no response buffering):
Using the ResponseBuffering middleware:
The results were surprising, faster average throughput when using ResponseBuffering with no real difference in memory usage so i then tried the same with a 10KB payload...
Throughput tests returning a 10KB JSON payload:
Default configuration (no response buffering):
Using the ResponseBuffering middleware:
The results were very close, so i then tried the same with a 100KB payload...
Throughput tests returning a 100KB JSON payload:
Default configuration (no response buffering):
Using the ResponseBuffering middleware:
Again, the results very close, but notice the significantly less memory overhead when using the Response Buffering middleware, so i then tried the same with a 1MB payload...
Throughput tests returning a 1MB JSON payload:
Default configuration (no response buffering):
Using the ResponseBuffering middleware:
With a 1MB payload the default configuration has faster throughput, but the memory overhead is still higher. Obviously a 1MB payload is excessive and the API should implement paging to split into multiple smaller requests, but for the purposes of testing it was worth seeing what the result would be.
Considering the significant issues that the default configuration without Response Buffering causes when errors occur during serialization, my tests show that it is well worth adding Response Buffering as there seems to be no benefit to not using it, only downsides.
Refer to this thread for a description of the issues:
#2285
I did a quick test from a separate machine over the network as a sanity check and the results were not much different, but i plan to do a better test in the future with a more of a production setup.
Update:
I added a test for 10MB payload and updated the results for the 1MB payload after double checking the my figures:
Throughput tests returning a 10MB JSON payload:
Default configuration (no response buffering):
Using the ResponseBuffering middleware:
The text was updated successfully, but these errors were encountered: