2021-02-06

.net模板引擎 jntemplate v2.0 测试, 要国产,也要速度

jntemplate 是一款国产的文本解析引擎(模板引擎),最近2.0的版本进行了重构,笔者在Gihub上挑了几个模板引擎做了一个简单的小对比测试,看下国产的质量怎么样!

环境说明:

操作系统:Windows 10.0.19041.746

CPU: Intel Xeon CPU E3-1231 v3 3.40GHz

内存:8G

.NET 框架:  net 5

测试工具:BenchmarkDotNet 0.12.1

参与测试的引擎:

JinianNet.JNTemplate 2.0.0
Mustachio 2.1.0
RazorEngineCore 2020.10.1
RazorLight 2.0.0-rc.3
Scriban 3.4.2

说明一下,Razor官方是视图引擎,不方便直接测试,所以找了二款基于Razor的第三方引擎来参与测试,其中RazorEngine因为版本太老无法支持.net 5,故选择了RazorLight 与RazorEngineCore 

以 上文件均从nuget安装。语法参照官文档编写并尽量统一。

 

测试一:输出一个变量或者属性

测试用代码:

using BenchmarkDotNet.Attributes;using JinianNet.JNTemplate;using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace Test{ [MemoryDiagnoser] public class TestVariable {  [Benchmark]  public void RunJntemplate()  {   var template = Engine.CreateTemplate("Hello $model.Id !");   template.Set("model", new UserInfo { Id = 10, Name = "your name!" });   var value = template.Render();  }  [Benchmark]  public void RunMustachio()  {   var template = Mustachio.Parser.Parse("Hello {{Id}} !");   dynamic model = new System.Dynamic.ExpandoObject();   model.Id = 10;   model.Name = "your name!";   var value = template(model);  }  [Benchmark]  public void RunScriban()  {   var template = Scriban.Template.Parse("Hello {{Id}} !");   var value = template.Render(new UserInfo { Id = 10, Name = "your name!" });  }  [Benchmark]  public void RunRazorEngineCore()  {   //RazorEngineCore.IRazorEngineCompiledTemplate template;   var razorEngine = new RazorEngineCore.RazorEngine();   var template = razorEngine.Compile("Hello @Model.Id");   var value = template.Run(new UserInfo { Id = 10, Name = "your name!" });  }  [Benchmark]  public void RunRazorLight()  {   var engine = new RazorLight.RazorLightEngineBuilder()    // required to have a default RazorLightProject type,    // but not required to create a template from string.    .UseEmbeddedResourcesProject(typeof(UserInfo))    //.SetOperatingAssembly(typeof(UserInfo).Assembly)    .UseMemoryCachingProvider()    .Build();   string template = "Hello @Model.Id";   var model = new UserInfo { Id = 10, Name = "your name!" };   string result = engine.CompileRenderStringAsync("templateKey", template, model).GetAwaiter().GetResult();  } }}

  

测试结果:

 

这里可以看到二个razor引擎所需要的时间是最长的,这是因为它们是编译型引擎,初始运行需要进行编译,所以会占用较多时间。

不过为什么jntemplate也是编译型引擎,所占时间却最少呢?

 

测试二:测试一的代码一共运行10万次

即然一次说明不了什么,接下来我们进行第二项测试,把上面的代码各运行10万次。

测试代码:

using BenchmarkDotNet.Attributes;using JinianNet.JNTemplate;using RazorEngineCore; using System.Collections.Concurrent; namespace Test{ [MemoryDiagnoser] public class TestVariableMultiple {  private int Max = 100000;  [Benchmark]  public void RunJntemplate()  {   string text = "Hello $model.Id";   var hashCode = text.GetHashCode().ToString();   for (var i = 0; i < Max; i++)   {    var template = JinianNet.JNTemplate.Engine.CreateTemplate(hashCode, text);    template.Set("model", new UserInfo { Id = 10, Name = "your name!" });    var value = template.Render();   }  }  [Benchmark]  public void RunScriban()  {   Scriban.Template template = Scriban.Template.Parse("Hello {{Id}} !");   for (var i = 0; i < Max; i++)   {    var value = template.Render(new UserInfo { Id = 10, Name = "your name!" });   }  }  [Benchmark]  public void RunMustachio()  {   var template = Mustachio.Parser.Parse("Hello {{Id}} !");   for (var i = 0; i < Max; i++)   {    dynamic model = new System.Dynamic.ExpandoObject();    model.Id = 10;    model.Name = "your name!";    var value = template(model);   }  }  [Benchmark]  public void RunRazorEngineCore()  {   var TemplateCache = new ConcurrentDictionary<int, IRazorEngineCompiledTemplate>();   string text = "Hello @Model.Id";   int hashCode = text.GetHashCode();   for (var i = 0; i < Max; i++)   {    IRazorEngineCompiledTemplate compiledTemplate = TemplateCache.GetOrAdd(hashCode, i =>    {     RazorEngine razorEngine = new RazorEngine();     return razorEngine.Compile(text);    });    var value = compiledTemplate.Run(new UserInfo { Id = 10, Name = "your name!" });   }  }  [Benchmark]  public void RunRazorLight()  {   var engine = new RazorLight.RazorLightEngineBuilder()     .UseEmbeddedResourcesProject(typeof(UserInfo))     .UseMemoryCachingProvider()    .Build();   string template = "Hello @Model.Id";   var model = new UserInfo { Id = 10, Name = "your name!" };   for (var i = 0; i < Max; i++)   {    if (i==0)    {     string result = engine.CompileRenderStringAsync("templateKey", template, model).GetAwaiter().GetResult();    }    else    {     var cacheResult = engine.Handler.Cache.RetrieveTemplate("templateKey");     if (cacheResult.Success)     {      var templatePage = cacheResult.Template.TemplatePageFactory();      string result = engine.RenderTemplateAsync(templatePage, model).GetAwaiter().GetResult();     }    }   }  } }}

  

测试结果:

 

运行10万次后,编译型引擎的速度明显占优

 

测试三:foreach 遍历10万次

测试代码:

using BenchmarkDotNet.Attributes;using JinianNet.JNTemplate;using RazorEngineCore;using System;using System.Collections.Concurrent;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace Test{ /// <summary> /// / /// </summary> [MemoryDiagnoser] public class TestForeach {  private int[] arr;  private int max = 100000;  public TestForeach()  {   arr = new int[max];   for(var i = 0; i < max; i++)   {    arr[i] = i;   }  }  [Benchmark]  public void RunScriban()  {   var template = Scriban.Template.Parse(@"<ul id='products'> {{ for product in products }} <li>{{ product }}</li> {{ end }}</ul>");   var result = template.Render(new { Products = arr });  }  [Benchmark]  public void RunJntemplate()  {   string text = @"<ul>$for(node in list)<li>$node</li>$end</ul>";   var hashCode = text.GetHashCode().ToString();   var template = JinianNet.JNTemplate.Engine.CreateTemplate(hashCode, text);   template.Set("list", arr);   var value = template.Render();  }  [Benchmark]  public void RunRazorEngineCore()  {   var razorEngine = new RazorEngineCore.RazorEngine();   var TemplateCache = new ConcurrentDictionary<int, IRazorEngineCompiledTemplate>();   string text = @"<ul>@{foreach (var item in Model){ <li>@item</li> }}</ul>";    var template = razorEngine.Compile(text);   var value = template.Run(arr);  }  [Benchmark]  public void RunRazorLight()  {   var engine = new RazorLight.RazorLightEngineBuilder()    // required to have a default RazorLightProject type,    // but not required to create a template from string.    .UseEmbeddedResourcesProject(typeof(UserInfo))    //.SetOperatingAssembly(typeof(UserInfo).Assembly)    .UseMemoryCachingProvider()    .Build();   string text = @"<ul>@{foreach (var item in Model){ <li>@item</li> }}</ul>";   string result = engine.CompileRenderStringAsync("templateKey", text, arr).GetAwaiter().GetResult();  } }}

  

测试结果:

 

mustachio没有找到怎么foreach的语法,这里就没测试,Scriban 支持不了这么大的数组,所以没有结果。

 

还有一些复杂的用法,今天暂时就不测了,结论我就不用说了,当然本次测试并不完整,毕竟一个引擎涉及到的地方很多,仅仅一二个用法不能代表不了全部,所以结果仅供参考。

另外mustachio功能上太简单,其实无法和其它引擎相提并论,这里只拿来只是凑个数!

 大家怎么看呢?









原文转载:http://www.shaoqun.com/a/530577.html

跨境电商:https://www.ikjzd.com/

topia:https://www.ikjzd.com/w/2741

四海商舟:https://www.ikjzd.com/w/1516


jntemplate是一款国产的文本解析引擎(模板引擎),最近2.0的版本进行了重构,笔者在Gihub上挑了几个模板引擎做了一个简单的小对比测试,看下国产的质量怎么样!环境说明:操作系统:Windows10.0.19041.746CPU:IntelXeonCPUE3-1231v33.40GHz内存:8G.NET框架:net5测试工具:BenchmarkDotNet0.12.1参与测试的引擎:Jin
折扣网:折扣网
递四方:递四方
2021渠道拓展必看:欧洲新卖家业务指南:2021渠道拓展必看:欧洲新卖家业务指南
收藏:亚马逊产品定价的策略很多,这几点最重要!:收藏:亚马逊产品定价的策略很多,这几点最重要!
如何分析广告数据,降低ACOS,提升转化率,看完这个你就知道了.:如何分析广告数据,降低ACOS,提升转化率,看完这个你就知道了.

No comments:

Post a Comment