.NET HttpWebRequest速度与浏览器

时间:2010-01-12 11:08:52

标签: c# .net httpwebrequest performance

我对.Net HttpWebRequest客户端(或WebClient,给出类似结果)的性能有疑问。

如果我使用HttpWebRequest请求一个html页面(在本例中为news.bbc.co.uk)并分析应用程序读取响应的速度(使用HttpAnalyzer),这明显慢于浏览器( Firefox,Chrome,IE)请求相同的资源(清除所有缓存等)。 .Net应用程序大约需要1.7秒,而浏览器需要0.2 - 0.3秒。

这纯粹取决于代码/应用程序的速度和效率,还是还有其他因素需要考虑?

代码如下:

HttpWebRequest request = null;

Uri uriTest = new Uri("http://news.bbc.co.uk");

request = (HttpWebRequest)WebRequest.Create(uriTest);

request.Method = "GET";
request.KeepAlive = true;
request.Headers["Accept-Encoding"] = "gzip, deflate";

HttpWebResponse response = (HttpWebResponse)request.GetResponse();

response.Close();

9 个答案:

答案 0 :(得分:2)

如果您提出两个请求,第二个请求会更快发生吗?

我还注意到浏览器与WebClient或WebRequest之间的速度差异。甚至响应的原始速度也可能大不相同 - 但并非总是如此!

这可能是由以下几点引起的:

  • 可能会发生所有.Net引导。 .Net程序集在使用之前不会加载和JIT,因此即使应用程序本身已经运行了很长时间,您也可以看到对一段代码的初始调用显着降低速度。好的 - 所以.Net框架本身就是nGen'd - 但是你的代码和.Net框架之间仍然存在着动态构建的桥梁。

  • 只是检查您是否在没有连接调试器的情况下运行,并且您肯定没有打开符号服务器 - 符号服务器和VS会在下载符号时中断程序,从而减慢它们的负载。对不起,如果这是侮辱;)

  • 浏览器的编码只能有效地使用少量底层套接字;一旦浏览器出现,它们就会被打开并启动。使用.Net WebClient / WebRequest的“我们的”代码相比之下完全没有效率,因为每次都会重新初始化所有内容。

  • 网络中有很多平台资源,虽然.Net使网络编码变得更加容易,但仍然存在相同的平台资源问题。因此,您越接近平台,一些代码就越快。 IE和Firefox等是原生的,因此本身可以抛出系统资源; .Net不是,因此需要一些编组(=慢)来进行设置。显然,一旦港口被打开并被使用,.Net仍然没有懈怠;但它几乎不会像编写良好的非编组本机代码一样快。

答案 1 :(得分:2)

首次请求页面时,.net会尝试检测代理设置。解决方案是传入一个空的WebProxy对象。这样它只是连接到远程服务器而不是自动检测代理服务器。

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uriTest);
request.Proxy = new WebProxy();

答案 2 :(得分:1)

您在使用浏览器时是否看过网络?也许浏览器正在使用缓存资源?

答案 3 :(得分:1)

我在中间插入Fiddler,一个接一个地运行浏览器请求和.NET请求,并确保你真正得到你的想法。这可能是重定向或其他一些正在发生的事情(可能是浏览器预先附加'/'而.NET等待redir等),这些都不是立即可见的。我已经在.NET HTTP客户端上构建了巨大的应用程序,没有你所描述的那样 - 其他必须要进行的事情。

如果您在网址末尾加上“/”会怎样?

答案 4 :(得分:1)

1.7s的细分是什么?我怀疑你是在衡量整个过程吗?

使用这段代码我平均得到大约200毫秒:

var request = (HttpWebRequest)WebRequest.Create("http://www.bbc.co.uk/news/");

var stopwatch = new Stopwatch();
stopwatch.Start();

using (var response = (HttpWebResponse)request.GetResponse())
{
    stopwatch.Stop();
    Console.WriteLine("Elapsed: {0}ms", stopwatch.ElapsedMilliseconds);

    var responseStream = response.GetResponseStream();
    if (responseStream != null)
        using (var sr = new StreamReader(responseStream))
            Console.WriteLine("Title: {0}", Regex.Match(sr.ReadToEnd(), @"title>(.*)</title").Groups[1].Value);
}

编辑 更改了代码,只是为了衡量实际的 HTTP请求,并尝试使用Fiddler:

上面的程序:经过时间:78毫秒

小提琴手:整体经历时间:00:00:00.0620000

答案 5 :(得分:1)

使用Ctrl + F5而不是F5(调试模式)运行应用程序。你会看到一个区别:

class Program
{
    static void Main()
    {
        using (var client = new WebClient())
        {
            Stopwatch watch = Stopwatch.StartNew();
            var data = client.DownloadData("http://news.bbc.co.uk");
            watch.Start();
            Console.WriteLine("{0} ms", watch.ElapsedMilliseconds);
        }
    }
}

在我的电脑上打印880毫秒。

答案 6 :(得分:0)

也许bbc.co.uk会检查传递给它的User-Agent header并根据它来处理响应。因此,如果它看到自动化客户端,那么它响应缓慢,就好像它认为在线路末端有真人,然后它加速。如果你真的想尝试一下,只需告诉HttpWebRequest传递一个不同的标题。

答案 7 :(得分:0)

每当您测量任何东西时,您都必须考虑启动成本。如果.net代码在一个进程中,并且您只测量单个请求,那么初始化程序集,类型等的初始成本会影响您的测量。

正如达林和其他人所建议的那样,你应该确保:

1)您没有在debuggger下运行该进程。 2)您考虑了启动成本。

你可以做#2的一种方法是发出两个请求,只测量第二个请求。或者您可以发出N个请求,丢弃第一个请求,并获得最后N-1个请求的平均值。还要确保您已阅读实体流。

答案 8 :(得分:0)

Markos的答案对我来说同样适用于同一个问题:

request.Proxy = new WebProxy();

将16秒的请求减少到不到一秒钟。谢谢!