zoukankan      html  css  js  c++  java
  • WebApiClient性能参考

    1 文章目的

    昨天写了走进WebApiClientCore的设计,介绍了WebApiClient的变化与设计之后,收到大家支持的、赞许的,还有好的建议和顾虑,比如WebApiClient性能怎么样,有没有一些对比参考值?我一直有个不好毛病,凭直接感观代码的运行效率,直觉里WebApiClient的代码都是优化的,就算性能不好,也没有更好的性能弥补方案!但真要这样和使用这个库的开发者说,相信要一秒内被打屎的,所以今天使用了BenchmarkDotNet对WebApiClient.JIT最新稳定版、WebApiClientCore预览版和原生的HttpClient做了请求和响应处理耗时对比。

    2 排除网络IO等待干扰

    我们必须要想办法去掉真实网络请求的时间干扰,因为一个请求回合中,网络等待时间可能会占用到整个流程的99.99%以上的时间。最好的办法就是没有请求,而是模拟一个响应内容。

    System.Net.Http支持管道式包装请求处理对象,叫DelegatingHandler,我们可以自定义一个DelegatingHandler,重写其SendAsync()方法,然后直接返回模拟的响应消息HttpResponseMessage,使用这个DelegatingHandler的HttpClient,在请求时不会真实将数据发送到目标服务器去。

    /// <summary>
    /// 无真实http请求的Handler
    /// </summary>
    class NoneHttpDelegatingHandler : DelegatingHandler
    {
        private readonly HttpResponseMessage benchmarkModelResponseMessage;
    
        public NoneHttpDelegatingHandler()
        {
            var model = new Model { A = "A", B = 2, C = 3d };
            var json = JsonSerializer.SerializeToUtf8Bytes(model);
            this.benchmarkModelResponseMessage = new HttpResponseMessage(HttpStatusCode.OK) { Content = new JsonContent(json) };
        }
    
        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            return Task.FromResult(this.benchmarkModelResponseMessage);
        }
    }
    

    3 Benchmark测试

    3.1 注册到DI

    为了公平,三种对比对象都注册到到DI里,使用时从DI获取实例

    var services = new ServiceCollection();
    
    // 原生HttpClient
    services
        .AddHttpClient(typeof(HttpClient).FullName)
        .AddHttpMessageHandler(() => new NoneHttpDelegatingHandler());
    
    // WebApiClientCore
    services
        .AddHttpApi<IWebApiClientCoreApi>(o => o.HttpHost = new Uri("http://webapiclient.com/"))
        .AddHttpMessageHandler(() => new NoneHttpDelegatingHandler());
    
    // WebApiClient
    WebApiClient.Extension
        .AddHttpApi<IWebApiClientApi>(services, o => o.HttpHost = new Uri("http://webapiclient.com/"))
        .AddHttpMessageHandler(() => new NoneHttpDelegatingHandler());
    

    3.2 Benchmark方法

    我们为三种客户端每个比较项目各写一个Benchmark方法:从DI获取实例,然后发起Get请求,最后将响应的内容反序列化为强模型。

    /// <summary>
    /// 使用WebApiClient.JIT请求
    /// </summary>
    /// <returns></returns>
    [Benchmark]
    public async Task<Model> WebApiClient_GetAsync()
    {
        using var scope = this.serviceProvider.CreateScope();
        var banchmarkApi = scope.ServiceProvider.GetRequiredService<IWebApiClientApi>();
        return await banchmarkApi.GetAsyc(id: "id");
    }
    
    /// <summary>
    /// 使用WebApiClientCore请求
    /// </summary>
    /// <returns></returns>
    [Benchmark]
    public async Task<Model> WebApiClientCore_GetAsync()
    {
        using var scope = this.serviceProvider.CreateScope();
        var banchmarkApi = scope.ServiceProvider.GetRequiredService<IWebApiClientCoreApi>();
        return await banchmarkApi.GetAsyc(id: "id");
    }
    
    /// <summary>
    /// 使用原生HttpClient请求
    /// </summary>
    /// <returns></returns>
    [Benchmark]
    public async Task<Model> HttpClient_GetAsync()
    {
        using var scope = this.serviceProvider.CreateScope();
        var httpClient = scope.ServiceProvider.GetRequiredService<IHttpClientFactory>().CreateClient(typeof(HttpClient).FullName);
    
        var id = "id";
        var request = new HttpRequestMessage(HttpMethod.Get, $"http://webapiclient.com/{id}");
        var response = await httpClient.SendAsync(request);
        var json = await response.Content.ReadAsByteArrayAsync();
        return JsonSerializer.Deserialize<Model>(json);
    }
    

    3.3 Benchmark运行与结果

    原于代码篇幅,实际中我们还加入了Post请求测试,所以最后的结果如下:

    BenchmarkDotNet=v0.12.1, OS=Windows 10.0.18363.836 (1909/November2018Update/19H2)
    Intel Core i7-8565U CPU 1.80GHz (Whiskey Lake), 1 CPU, 8 logical and 4 physical cores
    .NET Core SDK=3.1.201
      [Host]     : .NET Core 3.1.3 (CoreCLR 4.700.20.11803, CoreFX 4.700.20.12001), X64 RyuJIT
      DefaultJob : .NET Core 3.1.3 (CoreCLR 4.700.20.11803, CoreFX 4.700.20.12001), X64 RyuJIT
    
    
    |                     Method |      Mean |     Error |    StdDev |
    |--------------------------- |----------:|----------:|----------:|
    |      WebApiClient_GetAsync | 25.716 us | 0.5106 us | 0.9838 us |
    |  WebApiClientCore_GetAsync | 16.047 us | 0.1231 us | 0.0961 us |
    |        HttpClient_GetAsync |  2.028 us | 0.0240 us | 0.0224 us |
    |     WebApiClient_PostAsync | 18.712 us | 0.3707 us | 0.3641 us |
    | WebApiClientCore_PostAsync |  8.799 us | 0.1696 us | 0.1666 us |
    |       HttpClient_PostAsync |  3.673 us | 0.0710 us | 0.0972 us |
    

    总结

    不管是成熟稳定如狗的WebApiClient,还是新秀WebApiClientCore,其性能和原生的HttpClient在一个数量级,大家放心地使用就是了。

  • 相关阅读:
    【转载】Python未来互联网主流语言! . 天高地厚
    Android系统Intent的使用(转)
    android:获取联系人信息(姓名和电话)
    CMNET和CMWAP区别(转)
    Android界面开发推荐颜色
    android : framelayout 研究
    android : drag and drop ui
    android 四种模式研究之一
    ListView与CheckBox,EditText,Button结合
    android 之 custom view(一)
  • 原文地址:https://www.cnblogs.com/kewei/p/12930936.html
Copyright © 2011-2022 走看看