为什么JsonConvert比ASP.NET Core的内置Json Formatter更快?

时间:2017-06-19 03:47:45

标签: asp.net-core json.net .net-core asp.net-core-webapi asp.net-core-1.1

我了解到ASP.NET Core使用Newtonsoft.Json 9.0.1作为其内置的JSON格式化程序(Microsoft.AspNetCore.JsonPatch)。但是,我仍然没有弄清楚导致这两个代码之间性能差异的原因:

使用内置JSON格式化程序(Newtonsoft.Json 9.0.1)

[Produces("application/json")]
[Route("api/BuiltIn")]
public class BuiltInController : Controller
{
    private static readonly BufferBlock<ParentModel> Block = new BufferBlock<ParentModel>();

    // GET: api/BuiltIn
    [HttpGet]
    public ParentModel Get()
    {
        if (!Block.TryReceive(out ParentModel model)) return null;
        return model;
    }

    // POST: api/BuiltIn
    [HttpPost]
    public bool Post([FromBody]ParentModel model)
    {
        if (model == null) return false;
        return Block.Post(model);
    }
}
  

结果(10k请求):

     

POST - 64分19秒,GET - 57分8秒

使用JsonConvert(AspNetCore中引用的Newtonsoft.Json 9.0.1)

[Produces("application/json")]
[Route("api/JsonConvert")]
public class JsonConvertController : Controller
{
    private static readonly BufferBlock<ParentModel> Block = new BufferBlock<ParentModel>();

    // GET: api/JsonConvert
    [HttpGet]
    public ContentResult Get()
    {
        if (!Block.TryReceive(out ParentModel model)) return Content(null);
        return Content(JsonConvert.SerializeObject(model));
    }

    // POST: api/JsonConvert
    [HttpPost]
    public bool Post()
    {
        using (var reader = new StreamReader(Request.Body))
        {
            var request = reader.ReadToEnd();
            if (request == null) return false;
            var model = JsonConvert.DeserializeObject<ParentModel>(request);
            return Block.Post(model);
        }
    }
}
  

结果(10k请求):

     

POST - 63分47秒,GET - 56分18秒

无论我测试多少请求,直接使用JsonConvert都会提供稍好的性能(约1%)。这种性能差异的原因是什么?

2 个答案:

答案 0 :(得分:4)

除非您对其进行分析,否则我们无法告诉您。

但是你应该忽略这一点差异,这很可能是由于当你使用Content(...)Ok(...)辅助方法时触发了额外的GC,你也总是实例化一个ContentResult和/或OkObjectResult(请参阅BaseController.cs source),当直接返回模型时,这些可能会重复使用。

[NonAction]
public virtual OkObjectResult Ok(object value)
{
    return new OkObjectResult(value);
}

此外,您的测试很可能是错误的,因为ASP.NET Core能够每秒执行200k次请求(请参阅TechEmpower Benchmark, Round 14),或者您没有使用http Pipeline,而不是运行基准测试工具和ASP.NET应用于不同的物理计算机等。

更新

另请注意,public bool Post()的第二次测试不会调用模型绑定器,public bool Post([FromBody]ParentModel model)会这样做。当您将模型作为参数时,ASP.NET Core必须调用IModelBinderFactory.CreateBindersource)以获取正确的模型绑定器(即ComplexTypeModelBinder和其他模型绑定器,具体取决于模型的外观,例如ArrayModelBinderDictionaryModelBinderBodyModelBinder等。

因此,您的测试所做的是有效地测试模型绑定器的性能和/或ContentResult方法的return Content(string)实例化,以及 JSON.NET ASP.NET Core调用的直接与JSON.NET。

答案 1 :(得分:0)

随着.NET Core 3的发布,JSON序列化的性能将大大提高。

https://devblogs.microsoft.com/dotnet/try-the-new-system-text-json-apis/

博客文章还包含一些指标,概述了您可以预期的改进。