如何获得快速的.Net Http请求

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

我已经尝试过WinHTTP以及WebRequest.Create,它们都超过500毫秒,这对我的用例来说是不可接受的。

以下是我试图通过的简单测试的示例。 (WinHttpFetcher是我写的一个简单的包装器,但是它确实是一个获取请求的最简单的例子,我不确定它是否值得粘贴。)

我正在使用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); } 

在进行基准测试时,最好至少丢弃前两个时间,因为它们可能会扭曲结果:

  • 时序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; } 

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

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

VS.NET具有衡量性能的能力,您可能还想使用像Fiddler这样的东西来查看您花费多少时间“在线上”并且理智地检查它不是您的IIS / Web服务器导致延迟。

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

更新#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。 它被编译为调试,但我没有调试就运行它,我得到63毫秒 。 我在我的Windows 7笔记本电脑上运行它,因此http:// localhost会恢复默认的IIS7主页。 再次运行我得到类似的时间。

运行Release版本可以在50ms55ms范围内运行。

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

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

你可以在这里阅读它: – WebRequest慢吗?: http : //holyhoehle.wordpress.com/2010/01/12/webrequest-slow/


更新2018:从评论中提取。

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