代码之家  ›  专栏  ›  技术社区  ›  Nij

多线程WebRequest调用和争用

  •  3
  • Nij  · 技术社区  · 15 年前

    我正在运行一个多线程的C控制台应用程序。核心进程检索一些要处理的数据,将其拆分为可配置的数量较小的数据集,然后生成相同数量的线程来处理每个数据子集。

    要处理单个记录,线程必须使用WebRequest类和Post方法调用Web服务。使用getRequestStream()发送查询,使用getResponse()检索响应。

    在伪代码中,该例程如下所示:

    prepare WebRequest data;
    * get time (start-of-Processing);
    Stream str = request.GetRequestStream();
    Write data to stream;
    stream.Close();
    WebResponse resp = request.GetResponse();
    * get time (response-received);
    process response;
    finally close response stream;
    

    定时数据表明,当我们将数据拆分为4个以上的线程时,整个进程的吞吐量不会提高,在某些情况下甚至会下降。来自Web服务的定时数据保持其性能不变。

    • 在4个线程,我们的明显开销 发送数据并检索 响应流平均值约为 第二。
    • 当我们运行超过4个线程时, 最大值平均上升 遇到了几十秒!

    今天,我能够运行两个独立的进程,每个进程运行4个线程(但基本上确保每个线程仍然在唯一的数据上运行)。这一次,我们的总吞吐量几乎翻了一番,每个进程都有大约一秒钟的稳定时间。

    这让我相信我们正在对WebRequest类相关的资源进行某种限制;但这是一个单进程限制,而不是机器限制。我知道我们可以使用BeginGetRequestStream和BeginGetResponse异步进行调用,但我怀疑,如果我们实际上达到某种资源限制,它将产生积极影响?!

    我应该看什么才能使我们在不降低性能的情况下提高单个进程中的拆分数量?

    2 回复  |  直到 15 年前
        1
  •  13
  •   Jon Skeet    15 年前

    您需要增加可以同时向单个主机发出的Web请求的数量,否则线程将基本上等待彼此完成,尽管有大量的CPU可用。最简单的方法是使用 <connectionManagement> 元素 app.config :

    <configuration>
      <system.net>
        <connectionManagement>
          <add address = "*" maxconnection = "100" />
        </connectionManagement>
      </system.net>
    </configuration>
    
        2
  •  0
  •   Mike Dinescu    15 年前

    您运行此系统的计算机有多少个处理器/核心?

    当您调度的线程多于系统中的核心时,调度程序必须对每个线程进行时间切片,并调度它们在可用的核心上运行。所以,除非在你的过程中有死时间,否则性能不会增加,而且实际上可能会下降——这就是你所描述的。