I used a HttpHandler
to implement a light-weight web service targeted for high performance. It requires a POST
with content-type application/x-www-form-urlencoded
. The web service does many tasks including decryption, database work, business logic and so on. During load testing, the performance monitor (ANTS and Visual Studio) point to a single line of code that is taking the majority of time, in fact 67%.
string value = context.Request.Form[MY_FORM_KEY];
At the bottom of the call stack for this line of code, the performance monitor, says this call:
System.Web.Hosting.UnsafeIISMethods.MgdSyncReadRequest();
is the culprit.
Can anyone help please explain?! The application is in .Net 4, published as release, IIS 7, on Windows Server 2008.
Thank you,
Joey J. Barrett
Time delay occurs because IIS tries to read request stream from the client to retrieve form values. This stream is subject to client connection and in some causes will not even return. I have seen cases where Request.Form would block for over 5 minutes and it would cause IIS to eventually throw ThreadAbortException.
In our case, we had an HttpModule that had to read through Request.Form values (or request["key"] which iterates over form values as well) and it would randomly block on the server and would never return. I used this HttpModule to track application performance on server side, which made me realize that anything I track using this module will also be dependent on client's connectivity, which would skew my server-side execution results.
To resolve this issue, you can install reverse HTTP proxy in front of your application. Reverse proxy will off-load the responsibility of reading client stream (and blocking an expensive thread in your application) and send complete request to your server. This will reduce the load on your application, because you can save your precious application threads for dealing with your main workload rather than blocking them for reading from client streams.
In addition, you can off-load HTTPs, load-balance, and even cache some static content on your reverse proxy (depending on which one you use).
The
System.Web.Hosting.UnsafeIISMethods.MgdSyncReadRequest()
is an imported IIS function (as you may have guessed). Since http.sys, the bit that does all the http work for IIS, is unmanaged code, at some point your application will need to talk to it, although not directly.
What I guess is happening is when you read the form collection, .net is reading this from the raw request from IIS. If it's proving to be a bottle neck, I would refactor your code to read the form data asynchronously and store the values you need in a native data structure.
Simon
MgdSyncReadRequest
method blocked inner unmanaged-IIS API. But raised managed ThreadAbortException
.
That means another managed thread may be call Thread.Abort()
.
I searched referencesource, got it "RequestTimeoutManager
":
http://referencesource.microsoft.com/#System.Web/RequestTimeoutManager.cs,177
thread.Abort(new HttpApplication.CancelModuleException(true));
Solution (not inspect, may be): Implements by async-based reader, and handle time-out manually...