views:

2795

answers:

5

I am trying to measure the throughput of a webservice.

In order to do that, I have written a small tool that continuously sends requests and reads responses from a number of thread.

The contents of the inner loop of each thread looks like this:

public void PerformRequest()
{
  WebRequest webRequest = WebRequest.Create(_uri);

  webRequest.ContentType = "application/ocsp-request";
  webRequest.Method = "POST";
  webRequest.Credentials = _credentials;
  webRequest.ContentLength = _request.Length;
  ((HttpWebRequest)webRequest).KeepAlive = false;

  using (Stream st = webRequest.GetRequestStream())
    st.Write(_request, 0, _request.Length);

  using (HttpWebResponse httpWebResponse = (HttpWebResponse)webRequest.GetResponse())
  using (Stream responseStream = httpWebResponse.GetResponseStream())
  using (BufferedStream bufferedStream = new BufferedStream(responseStream))
  using (BinaryReader reader = new BinaryReader(bufferedStream))
  {
    if (httpWebResponse.StatusCode != HttpStatusCode.OK)
      throw new WebException("Got response status code: " + httpWebResponse.StatusCode);

    byte[] response = reader.ReadBytes((int)httpWebResponse.ContentLength);
    httpWebResponse.Close();
  }      
}

It seems to work okay, except that something seems to be limiting the tool. If I run two instances of the tool with each 40 threads, I get significantly more throughput than one instance with 80 threads.

I found the ServicePointManager.DefaultConnectionLimit property, which I set to 10000.

Is there any other settings in .NET or on my machine that can influence the performance? (I am running Vista, but I see the same problem on Windows Server 2003).

Perhaps some restrictions on how many connections a single process can make?

+2  A: 

it could be the connection limit that has been imposed recently.

http://www.speedguide.net/read_articles.php?id=1497

and

http://www.mydigitallife.info/2007/04/09/windows-vista-tcpipsys-connection-limit-patch-for-event-id-4226/

shaunf
I don't get the entry in the eventlog, so I don't think that is it. It was a good suggestion, though. Thanks!
Rasmus Faber
+1  A: 

have you tried increasing the max connections in the network settings?

http://msdn.microsoft.com/en-us/library/fb6y0fyc.aspx

shaunf
A: 

How are you creating your threads? I assume that since you know you have 80 threads, you're not using the threadpool manager, because with the threadpool manager you can ask for as many threads as you like and you'll only get 25 active threads at a time. If you create the threads manually with an array then you'll actually get as many as you need, however they are still in the same process space, so that might limit them over threads running in separate processes.

You might also look into which apartment style the threads are getting created with, I believe the Thread class ctor uses STA by default. Try MTA and see if they affects performance.

LoveMeSomeCode
Only the initial version (or perhaps the first beta) of the 1.0 framework used STA threads. Keep in mind too that this threading context only has to deal with COM interop and the COM model. Unless they're using a COM object it doesn't matter here.
Peter Oehlert
You can set the threading model of your entry point with SetApartmentThread or the STAThreadAttribute in .NET 2.0 like this:http://msdn.microsoft.com/en-us/library/system.threading.thread.setapartmentstate(VS.80).aspx
LoveMeSomeCode
Right but by default .Net threads do not have an apartment specified and will specify one when using an object. Further, the thread apartment is still only important if you're either being used as a com object (CCW) or using a com object (RCW).
Peter Oehlert
A: 

Keep in mind multithreaded code can always cause contention on any shared resources and even if you're not explicitly sharing anything you might be using classes that are sharing resources under the covers.

If you are really getting better performance with 2 40 thread exes than 1 80 thread exe then you'll need to start your investigation with shared resources. And if that is the case, the code you cited is far less interesting than the code that creates and manages the threads.

The other thing I'd throw out there is there are several tools that you can get that will do this type of thing for you generically. See http://support.microsoft.com/kb/231282. Also included in Visual Studio (I'm not sure what skus) is a new generation of web application performance testing tools. And I'm sure if you looked you could find some non-MS stuff too.

Peter Oehlert
+6  A: 

You must set the maxconnection parameter at the app.config or web.config file:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.net>
    <connectionManagement>
      <add address="*" maxconnection="80"/>
    </connectionManagement>
  </system.net>
</configuration>

Values up to 100 work very well with Windows XP.

Update: I just found out that the method above is an alternative way to set the System.Net.ServicePointManager.DefaultConnectionLimit

Jader Dias
That last update seems to be the perfect way to find out wat maxconnections is set to when using autoConfig="true" in processModel. Just adding some keywords so that other people will be able to find this answer
Jauco