Your ASP.NET applications can experience poor performance if they use the common Response.Flush API to flush responses.
ASP.NET applications often use the Response.Flush() API to explicitly flush page response to the client. This can cause performance problems for some sites, in some cases leading to queueing and site-wide hangs.
Why does Response.Flush cause bad performance in ASP.NET?
By default, ASP.NET responses are automatically buffered in memory, and sent to the client at the end of the request. The final send is done asynchronously by the HTTP.SYS kernel driver, and does not block request threads.
When an ASP.NET application explicitly flushes with the Response.Flush API, it causes a synchronous send that blocks the ASP.NET request thread until the client receives the response data. If the client is slow or has disconnected, this can take a long time.
Mobile clients, clients on slow networks, or network congestion can rapidly escalate Response.Flush blocking into a site-wide hang.
If enough threads become blocked in Response.Flush calls, thread shortages will cause ASP.NET to become slower in responding to new requests and executing other application tasks. When the CLR thread pool becomes exhausted, requests will start to queue, causing a hang.
Important: Even Response.Flush calls in a single page can cause queueing delays and hangs for all requests to your application.
How do I remove Response.Flush calls?
Use these techniques to eliminate Response.Flush, from easiest to hardest:
- Simply remove calls to Response.Flush, and let normal buffering take place.
- If you are sending a file, use HttpResponse.TransmitFile instead.
- Implement asynchronous flush with HttpResponse.BeginFlush (Requires .NET 4.5+)
- Implement streaming with ASP.NET WebAPI (Requires .NET 4.5+, WebSockets).
How do I know that I have a problem?
If your application is experiencing intermittent slowdowns or hangs, you should check for the Response.Flush issue.
Here are the easiest ways to do it:
- Use LeanSentry. LeanSentry's Hang Diagnostics will automatically detect slowdowns/hangs, and identify response flushes in the middle of request processing as the cause.
- Use the IIS Failed Request Tracing (FRT) feature. Collect slow request traces, and inspect the traces for response flushes in the middle of ASP.NET processing.
You may need to review many traces over time to detect this, because this issue may be intermittent.
NOTE: Unfortunately, the IIS “Executing requests” feature will generically show requests performing explicit flushes as stuck in the application handler (ManagedPipelineHandler), so you will not be able to differentiate response flushing from any other application-level blocking cause.