views:

2495

answers:

1

I have a small tool I use for testing a webservice.

It can either call the webservice using POST or using GET.

The code for using POST is

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();
  }      
}

The code for using GET is:

protected override void PerformRequest()
{
  WebRequest webRequest = WebRequest.Create(_uri + "/" + Convert.ToBase64String(_request));

  webRequest.Method = "GET";
  webRequest.Credentials = _credentials;
  ((HttpWebRequest)webRequest).KeepAlive = false;

  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();
  }
}

As you can see the code is quite similar. If anything, I would expect the GET-method to be slightly slower, as it has to encode and transmit the data in Base64.

But when I run it, I see that the POST-method uses far more processing power than the GET-method. On my machine, I can run 80 threads of the GET-method using approximately 5% CPU, while 80 threads of the POST-method uses 95% CPU.

Is there something inherently more expensive about using POST? Is there anything I can do to optimize the POST-method? I cannot reuse the connection, as I want to simulate requests from different clients.

dotTrace reports that 65% of the processing-time is spent in webRequest.GetResponse() when using POST.

The underlying webservice uses Digest-Authentication if that makes any difference.

+2  A: 

Well, depending on the complexity of the final uri, it might be that the "GET" requests are being cached? "POST" is not cached by default, but "GET" often is (as it should be idempotent). Have you tried sniffing to see if there is any difference here?

Also - you might find WebClient easier to use - something like:

using (WebClient wc = new WebClient())
{
    byte[] fromGet = wc.DownloadData(uriWithData);
    byte[] fromPost = wc.UploadData(uri, data);
}
Marc Gravell
Yes, POST is defined to change the server state while GET does not
Matt