.net 什么可能会导致HttpWebRequest调用的巨大开销?

.net 什么可能会导致HttpWebRequest调用的巨大开销?,.net,silverlight,performance,http,httpwebrequest,.net,Silverlight,Performance,Http,Httpwebrequest,当我使用HttpWebRequest(在Silverlight上)在小块中发送/接收数据时,我测量了“localhost”连接上500字节/秒的非常小的吞吐量。当以大数据块的形式发送数据时,我的速度为2MB/s,比以前快5000倍 有人知道是什么导致了这么大的开销吗 其他信息: 我正在使用HTTPPOST方法 我在Firefox3.6和InternetExplorer7上都做了性能测试。两者的结果相似 我的CPU只加载了10%(四核,实际上是40%) WebClient显示了类似的结果 更

当我使用HttpWebRequest(在Silverlight上)在小块中发送/接收数据时,我测量了“localhost”连接上500字节/秒的非常小的吞吐量。当以大数据块的形式发送数据时,我的速度为2MB/s,比以前快5000倍

有人知道是什么导致了这么大的开销吗

其他信息:

  • 我正在使用HTTPPOST方法
  • 我在Firefox3.6和InternetExplorer7上都做了性能测试。两者的结果相似
  • 我的CPU只加载了10%(四核,实际上是40%)
  • WebClient显示了类似的结果
更新:我使用的Silverlight客户端代码本质上是我自己的WebClient类实现。我之所以写这篇文章,是因为我注意到WebClient存在同样的性能问题,我认为HttpWebRequest可以调整性能问题。遗憾的是,这没有起作用。实施情况如下:

public class HttpCommChannel
{
    public delegate void ResponseArrivedCallback(object requestContext, BinaryDataBuffer response);

    public HttpCommChannel(ResponseArrivedCallback responseArrivedCallback)
    {
        this.responseArrivedCallback = responseArrivedCallback;
        this.requestSentEvent = new ManualResetEvent(false);
        this.responseArrivedEvent = new ManualResetEvent(true);
    }

    public void MakeRequest(object requestContext, string url, BinaryDataBuffer requestPacket)
    {
        responseArrivedEvent.WaitOne();
        responseArrivedEvent.Reset();

        this.requestMsg = requestPacket;
        this.requestContext = requestContext;

        this.webRequest = WebRequest.Create(url) as HttpWebRequest;
        this.webRequest.AllowReadStreamBuffering = true;
        this.webRequest.ContentType = "text/plain";
        this.webRequest.Method = "POST";

        this.webRequest.BeginGetRequestStream(new AsyncCallback(this.GetRequestStreamCallback), null);
        this.requestSentEvent.WaitOne();
    }

    void GetRequestStreamCallback(IAsyncResult asynchronousResult)
    {
        System.IO.Stream postStream = webRequest.EndGetRequestStream(asynchronousResult);

        postStream.Write(requestMsg.Data, 0, (int)requestMsg.Size);
        postStream.Close();

        requestSentEvent.Set();
        webRequest.BeginGetResponse(new AsyncCallback(this.GetResponseCallback), null);
    }

    void GetResponseCallback(IAsyncResult asynchronousResult)
    {
        HttpWebResponse response = (HttpWebResponse)webRequest.EndGetResponse(asynchronousResult);
        Stream streamResponse = response.GetResponseStream();
        Dim.Ensure(streamResponse.CanRead);
        byte[] readData = new byte[streamResponse.Length];
        Dim.Ensure(streamResponse.Read(readData, 0, (int)streamResponse.Length) == streamResponse.Length);
        streamResponse.Close();
        response.Close();

        webRequest = null;
        responseArrivedEvent.Set();
        responseArrivedCallback(requestContext, new BinaryDataBuffer(readData));
    }

    HttpWebRequest webRequest;
    ManualResetEvent requestSentEvent;
    BinaryDataBuffer requestMsg;
    object requestContext;
    ManualResetEvent responseArrivedEvent;
    ResponseArrivedCallback responseArrivedCallback;
}
我使用此代码将数据来回发送到HTTP服务器


更新:经过广泛的研究,我得出结论。

我怀疑您的问题只是延迟。任何消息都需要一段时间才能到达服务器,并进行解析和处理,生成响应,而响应需要一段时间才能返回到客户端,并被解析为可用的响应。你的表现很可能是由往返时间决定的

基本上,任何跨越通信边界的接口——无论是进程间还是机器间——都应该是“粗块”而不是“闲聊”。在每个请求中发送尽可能多的信息,并在响应中获取尽可能多的数据。在同一台机器上,这可能看起来微不足道,但我看到应用程序服务器的性能提高了十倍,方法是在工作进程中批量执行命令,而不是针对每个命令从工作进程回调到主服务器进程


您确实回答了自己的问题,指出当您使用大的块大小时,您会获得更好的性能。

正如Mike Dimmick在其回答中提到的,延迟问题可能会导致问题,但是,除了在数据有效负载非常小的情况下出现延迟问题外,还要分配线程以执行(即使使用线程池)与批量有效负载路由相比,连接建立后所花费的时间占总时间的百分比要大得多。

很可能您看到了Nagle算法的效果,请尝试:

this.webRequest.UseNagleAlgorithm.ServicePoint = false;
此外,Expect100Continue“握手”与soap服务调用性能相关:

this.webRequest.Expect100Continue.ServicePoint = false;
乌德帕特:

刚刚意识到ServicePoint在Compact框架中不可用。但是,您可以通过以下方式证明这一点:

ServicePointManager.UseNagleAlgorithm = false

或者更改应用程序配置文件中的相关设置,或者silverlight中的任何等效设置?

请显示一些代码-如果不看到代码,很难判断发生了什么。“使用大的块大小”:我不理解的是系数5000,对我来说似乎高得离谱。“在CF中不可用”:CF是什么意思?对不起,我把Compact Framework和Silverlight混淆了。因此,在使用GetResponse()发出http请求之前,我不确定ServicePoint对象是否在silverlight中可用。在CF中,该对象创建较晚,以减少资源使用。虽然我无法测试它,但您可能对Nagle延迟的看法是正确的。我没有想到这一点。遗憾的是,看起来UseNagleAlgorithm在Silverlight中不可用。无论如何,非常感谢您的回复!至少我现在明白了问题所在。哇,这让我想起了往事。我们12年前就遇到了这个问题;我们会以16赫兹的频率发送环境更新数据包,但很惊讶地看到它们以4赫兹的频率一组四个地出现。幸运的是,我们在Linux上使用C++,所以有一个标志,我们可以传递到套接字关闭这个。我们不知道它被称为“Nagle算法”,但我们总是称它为“数据包合并”