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

时间:2010-12-02 14:25:01

标签: c# .net http httpwebrequest libcurl

我需要一个可以在.Net中使用的Http请求,该请求不到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);
    }

3 个答案:

答案 0 :(得分: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;
}

答案 1 :(得分:4)

使用StopWatch课程来获得准确的时间安排。

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

VS.NET具有衡量性能的能力,您可能还想使用类似Fiddler之类的内容来查看您在线上花费了多少时间并且理智地检查它不是您的IIS /网络服务器导致延迟。

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进行操作。它被编译为调试,但我没有调试就运行它,我得到 63ms 。我在我的Windows 7笔记本电脑上运行它,因此http://localhost带回默认的IIS7主页。再次运行我得到类似的时间。

运行发布版本会在 50ms 55ms 范围内提供时间。

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

答案 2 :(得分: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 17年7月22日在5:44