web-dev-qa-db-ja.com

.NETでのマルチスレッドHttpWebRequestsのパフォーマンスの向上

Webサービスのスループットを測定しようとしています。

そのために、リクエストを継続的に送信し、多数のスレッドからレスポンスを読み取る小さなツールを作成しました。

各スレッドの内部ループの内容は次のようになります。

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

何かがツールを制限しているように見えることを除いて、それは問題なく動作しているようです。 40スレッドごとにツールの2つのインスタンスを実行すると、80スレッドの1つのインスタンスよりもスループットが大幅に向上します。

10000に設定したServicePointManager.DefaultConnectionLimitプロパティを見つけました(app.configで設定しても違いはありません Jader Diasが提案 )。

パフォーマンスに影響を与える可能性のある他の設定が.NETまたは私のマシンにありますか? (Vistaを実行していますが、Windows Server 2003でも同じ問題が発生します)。

おそらく、単一のプロセスが作成できる接続の数にいくつかの制限がありますか?

29
Rasmus Faber

App.configまたはweb.configファイルでmaxconnectionパラメーターを設定する必要があります。

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

100までの値は、WindowsXPで非常にうまく機能します。

更新:上記の方法がSystem.Net.ServicePointManager.DefaultConnectionLimitを設定する別の方法であることがわかりました

37
Jader Dias

ネットワーク設定で最大接続数を増やしてみましたか?

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

2
shaunf
2
shaunf

マルチスレッドコードは、共有リソースで常に競合を引き起こす可能性があることに注意してください。明示的に何も共有していない場合でも、内部でリソースを共有しているクラスを使用している可能性があります。

1 80スレッドexeよりも240スレッドexeの方がパフォーマンスが本当に向上している場合は、共有リソースを使用して調査を開始する必要があります。その場合、引用したコードは、スレッドを作成および管理するコードよりもはるかに面白くありません。

私がそこに捨てるもう一つのことは、あなたが一般的にあなたのためにこのタイプのことをするあなたが得ることができるいくつかのツールがあるということです。 http://support.Microsoft.com/kb/231282 を参照してください。また、Visual Studio(どのskusかはわかりません)には、新世代のWebアプリケーションパフォーマンステストツールが含まれています。そして、あなたが見れば、MS以外のものも見つけることができると確信しています。

1
Peter Oehlert

パフォーマンスには2つの重要な側面があります。

  1. 1つの側面は、すべての人が示唆しているように、数のTCP接続がクライアントによって使用されている(これらの接続が一般的に優れている場合)詳細については、永続化されます(keep alive = true)): http://msdn.Microsoft.com/en-us/library/system.net.servicepoint.connectionlimit(v = vs.110).aspxhttpwebrequestでTCP接続が作成された方法と場所、およびサービスポイントとどのように関連していますか?なぜSystem.Net。 ServicePoint.ConnectionLimitは、クライアントが「localhost」上のサービスに接続するときに「7FFFFFFF」(Int32.MaxValue/2147483647)を使用しますか?System.Net.ServicePointManager.DefaultConnectionLimitおよび.MaxServicePointIdleTime

  2. 2番目の側面は、複数の新しいスレッドを使用したり、ワーカースレッドを使用して、コードスニペットで同期呼び出し(httpwebrequest.getrequeststreamなど)を使用して並列作業を行うのではなく、非同期モデルを完全に採用する(ex、begin/endrequeststream、または新しいタスクのバリエーションの場合)。このようにすると、CPUは常にビジー状態になり、I/O完了ポートスレッドは、コールバックを呼び出して、ワーカー(スレッドプール)スレッドで応答を送信するだけです。 (以下を参照してください: 。NETはIOスレッドまたはIO完了ポート?http://blog.marcgravell.com/2009/02/async-without-pain.htmlHttpWebRequestおよびI/O完了ポート

よろしく。

0
Dreamer