2010-12-02 49 views
10

我需要一个Http请求,我可以在.Net中使用,这需要100毫秒以下。我能够在浏览器中实现这一点,所以我真的不明白为什么这是代码中的这样一个问题。如何获得一个快速的.Net Http请求

我试过WinHTTP以及WebRequest.Create,它们都超过500毫秒,这是我的用例不能接受的。

这里是我试图通过的简单测试的例子。 (WinHttpFetcher是我写的一个简单的包装,但它确实是Get Request的最微不足道的例子,我不确定它是否值得粘贴。)

我得到了LibCurlNet的可接受结果,但如果同时使用我得到一个访问冲突。另外,由于它不是托管代码,必须复制到bin目录,因此使用我的开源项目进行部署并不理想。

想要尝试另一个实现的任何想法?

[Test] 
    public void WinHttp_Should_Get_Html_Quickly() 
    { 
     var fetcher = new WinHttpFetcher(); 
     var startTime = DateTime.Now;   
     var result = fetcher.Fetch(new Uri("http://localhost")); 
     var endTime = DateTime.Now; 
     Assert.Less((endTime - startTime).TotalMilliseconds, 100); 
    } 
    [Test] 
    public void WebRequest_Should_Get_Html_Quickly() 
    { 
     var startTime = DateTime.Now; 
     var req = (HttpWebRequest) WebRequest.Create("http://localhost"); 
     var response = req.GetResponse(); 
     var endTime = DateTime.Now; 
     Assert.Less((endTime - startTime).TotalMilliseconds, 100); 
    } 
+0

的问题不是HttpWebRequest的。我通常会在连接到本地主机的大约13ms内收到请求。你确定它不是服务器吗? – 2010-12-02 14:44:41

回答

16

基准时,它是最好的,因为它们很可能扭曲结果丢弃至少第一两个定时:

  • 定时1:由JIT开销主导即将字节码转换为本地码的过程。
  • 时间2:JIT代码可能的优化过程。

此后的计时会反映出重复性能好得多。

以下是一个测试工具的示例,它会自动忽略JIT和优化传递,并在采用平均值来确定性能之前运行一系列迭代测试。正如你所看到的JIT通行证需要大量的时间。

JIT:410.79ms

优化:0.98ms

平均超过10次迭代:0.38ms

代码:

[Test] 
public void WebRequest_Should_Get_Html_Quickly() 
{ 
    private const int TestIterations = 10; 
    private const int MaxMilliseconds = 100; 

    Action test =() => 
    { 
     WebRequest.Create("http://localhost/iisstart.htm").GetResponse(); 
    }; 

    AssertTimedTest(TestIterations, MaxMilliseconds, test); 
} 

private static void AssertTimedTest(int iterations, int maxMs, Action test) 
{ 
    double jit = Execute(test); //disregard jit pass 
    Console.WriteLine("JIT:{0:F2}ms.", jit); 

    double optimize = Execute(test); //disregard optimize pass 
    Console.WriteLine("Optimize:{0:F2}ms.", optimize); 

    double totalElapsed = 0; 
    for (int i = 0; i < iterations; i++) totalElapsed += Execute(test); 

    double averageMs = (totalElapsed/iterations); 
    Console.WriteLine("Average:{0:F2}ms.", averageMs); 
    Assert.Less(averageMs, maxMs, "Average elapsed test time."); 
} 

private static double Execute(Action action) 
{ 
    Stopwatch stopwatch = Stopwatch.StartNew(); 
    action(); 
    return stopwatch.Elapsed.TotalMilliseconds; 
} 
4

使用StopWatch类可以获得准确的计时。

然后,通过在发布代码中多次运行您的时序测试,确保没有看到未优化代码或JIT编译的结果。放弃前几个电话以消除他对JIT的影响,然后采取其余的平均消息。

VS.NET具有测量性能的能力,你可能也想使用类似Fiddler,看看你有多少时间花费“上线”和完整性检查,这不是导致你的IIS/Web服务器延误。

500ms是一个很长的时间,并且有可能在这些类的ms中有10个,所以不要放弃希望(还)。

更新#1:

这是一个伟大的一篇文章,谈到微基准测试和什么需要避免看到喜欢的东西JIT:

http://blogs.msdn.com/b/vancem/archive/2009/02/06/measureit-update-tool-for-doing-microbenchmarks.aspx

你不太微基准测试,但这里有很多最佳实践。

更新#2:

所以,我写了这个控制台应用程序(使用VS.NET 2010)...

class Program 
{ 
    static void Main(string[] args) 
    { 
     var stopwatch = Stopwatch.StartNew(); 
     var req = (HttpWebRequest)WebRequest.Create("http://localhost"); 
     var response = req.GetResponse(); 
     Console.WriteLine(stopwatch.ElapsedMilliseconds);    
    } 
} 

...和Ctrl-F5'd它。它被编译为调试,但我运行它没有调试,我得到了63ms。我在我的Windows 7笔记本电脑上运行此操作,因此http://localhost带回了默认的IIS7主页。再次运行我得到相似的时间。

运行发布版本给出50ms的时间55ms范围。

这是我期望的数量级。显然,如果您的网站正在执行ASP.NET重新编译,或回收应用程序池,或执行大量后端处理,那么您的时间将有所不同。如果你的标记很大,那么它也会有所不同,但是你使用客户端的类都不应该是这里的限速步骤。这将是网络希望和/或远程应用处理。

+1

+1总是扔掉至少前两个结果将是JIT,然后可能是一个优化通过。 – 2010-12-02 15:11:47

+0

我已经尝试了很多次发布模式,它仍然很慢。我真的怀疑秒表是否会超过30ms左右的数量级,所以我相信我的测试仍然有效。 – 2010-12-02 16:53:18

1

尝试将HttpWebRequest实例的Proxy属性设置为null。 如果可行,请尝试将其设置为GlobalProxySelection.GetEmptyWebProxy(),这似乎更加正确。

您可以阅读铁道部关于在这里:​​ - WebRequest的慢?:http://holyhoehle.wordpress.com/2010/01/12/webrequest-slow/


更新2018:从注释中拉这件事。

System.Net.GlobalProxySelection已过时。此类已被弃用。请使用WebRequest.DefaultWebProxy来访问并设置全局默认代理。使用null而不是GetEmptyWebProxy()。 - jirarium 07月22日在'17 5:44