I recently tried running a .NET application on 64bit versions of Windows and was surprised to notice that all my HttpWebRequest.GetResponse()
calls to web services on my local network were talking huge (around 500ms) time to complete. Here's a few info regarding my test setup:
The test code is a slightly modified version of the example described in MSDN's article on HttpWebRequest.GetResponse
. The only modifications I performed were just a loop so that I could time 10 consequtive calls, and Basic Authentication, since the web service I was targeting needed authentication:
using System;
using System.Diagnostics;
using System.Net;
using System.Text;
using System.IO;
public class Program
{
// Specify the URL to receive the request.
public static void Main (string[] args)
{
CredentialCache crCache = null;
Stopwatch s = new Stopwatch();
for (int i = 0; i < 10; i++)
{
s.Reset();
s.Start();
HttpWebRequest request =
(HttpWebRequest)WebRequest.Create (args[0]);
// Set some reasonable limits on resources used by this request
request.MaximumAutomaticRedirections = 4;
request.MaximumResponseHeadersLength = 4;
// Set credentials to use for this request.
if (crCache == null)
{
crCache = new CredentialCache();
crCache.Add(new Uri(args[0]), "Basic",
new NetworkCredential("user", "password"));
}
request.Credentials = crCache;
request.PreAuthenticate = true;
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Console.WriteLine("Content length is {0}", response.ContentLength);
Console.WriteLine("Content type is {0}", response.ContentType);
// Get the stream associated with the response.
Stream receiveStream = response.GetResponseStream();
// Pipes the stream to a higher level stream reader with the required encoding format.
StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8);
Console.WriteLine("Response stream received.");
//Console.WriteLine (readStream.ReadToEnd ());
response.Close();
readStream.Close();
s.Stop();
Console.WriteLine("Request took: " + s.ElapsedMilliseconds);
}
}
}
I compiled the program targeting x86 for Windows Vista Home Premium and x64 for the 64bit Windows machines. The three machines were connected on the same network switch together with the machine hosting the web service. Here are the results I got:
GetResponse()
was completed in around 150ms, while all consecutive calls took around 10ms.HttpWebRequest.PreAuthenticate
, each GetResponse
completes in 1000ms (which is quite reasonable since in this case each request triggers two separate HTTP requests, one ending up with Unauthorized and one the gets the proper response).Does anybody have a clue of the reason I get such long GetResponse
delays on the 64 bit versions of Windows?
Additional information for the problem:
32bit: The tcp conversation is as follows:
64 bit: The tcp conversation is as follows:
The 500ms I get on the 64 bit machines is mostly occured in the last two steps. Note that this is definitely not related to the TCP stack (since everything works ok with firefox). The reason we get different TCP Ack pattern in the last two steps (piggybacked in 32 bit, while separate TCP Ack frame in 64 bit) is that the new Web Request is delayed for 309+96ms in the 64bit case (so the TCP stack outputs a separate Ack frame, it can not wait for the application layer).
So, it seems like:
Any clues?
Just for anyone else that comes across this thread and is having issues.
The cause of the delay on 64bit systems is the WebClient waiting for Windows to return the proxy value.
Write your code like this to overcome this issue.
WebClient wc = New WebClient;
wc.Proxy = null;
That will eliminate the delay seen by some users (including myself :))
Glad I could finally give something back to the community that has helped me so much :)
I was having this same exact issue and it drove me crazy as I have 2 webapps calling an api webapp on the same server. I kept getting 500ms response times. If I made multiple calls to my api using the WebRequest object each one would take around 500ms.
This was my solution for my particular situation. My Windows Server 2008 RC2 64bit box has Nod32 running. It has a feature called "Web Access Protection". Turn off http/https scanner. My response times then went from a consistent 500ms to 30-60ms.
Solution for me was:
ServicePointManager.UseNagleAlgorithm = false
Note that you have to set this before you create your HttpWebRequest objects. Didn't work for me if I set it afterwards.
Speed increase was huge because we create lots of small JSON requests. Probably 10x faster.
Can you make sure that
<system.net><settings><servicePointManager useNagleAlgorithm="false"/>
and try again?
If it still fails, is there a content-length header? Same value in both cases? And, last, but not least, are there extra bytes in the response? Oh, and you should enable the line:
//Console.WriteLine (readStream.ReadToEnd ());
just to make sure that reusing a connection will happen (it might happen without that, but just in case).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With