热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

NVelocity1.1vsStringTemplate3.2

拿NVelocity1.1、StringTemplate3.2和ASP.NET的ASPX页面做了个性能测试对比,对比结果如下:结果就是,在
拿NVelocity 1.1、StringTemplate 3.2和ASP.NET的ASPX页面做了个性能测试对比,对比结果如下:
    NVelocity、StringTemplate与ASPX解析性能对比
结果就是,在2台不同的机器上,ASPX:StringTemplate:NVelocity分别为1.00:8.53:1.61和1.00:7.34:1.71,StringTemplate的性能最弱,NVelocity有点接近ASPX的解析效率。测试过程中还发现,几点:
1. 对StringTemplate,不应该连续使用StringTemplateGroup太多次,每一个任务新建一个StringTemplateGroup性能要好很多
2. 之前的某些版本,连续使用同一个StringTemplateGroup对象多次获取模板,存在严重的内存泄漏问题,性能也非常差,3.2版本性能好了很多,也没有出现内存泄漏
3. StringTemplate还有一些bug,例如下面列表测试中的Dictionary、DataTable,在3.2版本下无法读取到值(3.1的版本在列表情况下可以读取到DataTable)
测试用的项目文件: 下载

测试辅助类:


using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Web;
using Antlr3.ST;
using Commons.Collections;
using NVelocity;
using NVelocity.App;
using NVelocity.Runtime;


public class Contact
{public string Name { get; set; }public string EMail { get; set; }public string Address { get; set; }public decimal TotalOrderAmt { get; set; }//StringTemplate不支持模板中的比较判断&#xff0c;因此在这里处理public bool IsLevel3{get{return this.TotalOrderAmt > 1000;}}public bool IsLevel2{get{return this.TotalOrderAmt <&#61; 1000 && this.TotalOrderAmt > 200;}}public bool IsLevel1{get{return this.TotalOrderAmt <&#61; 200;}}
}


public class TemplateUtil
{private static string ST_ROOT_PATH &#61; string.Empty;static TemplateUtil(){string rootDir &#61; HttpContext.Current.Server.MapPath("./st");if (rootDir.EndsWith("\\")) rootDir &#61; rootDir.Substring(0, rootDir.Length - 1);ST_ROOT_PATH &#61; rootDir;}public static void WriteTime(string title, long time){HttpContext.Current.Response.Write("
" &#43; title);long millisecondes &#61; time % 1000;long minutes &#61; time / 1000 / 60;long seconds &#61; (time - minutes * 60 * 1000) / 1000;if (minutes > 0)HttpContext.Current.Response.Write(minutes.ToString() &#43; "m, ");if (seconds > 0)HttpContext.Current.Response.Write(seconds.ToString() &#43; "s, ");HttpContext.Current.Response.Write(millisecondes.ToString() &#43; "ms");}public static long NVelocityTest(int loops){VelocityEngine engine &#61; new VelocityEngine();ExtendedProperties prop &#61; new ExtendedProperties();prop.AddProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, HttpContext.Current.Server.MapPath("./"));prop.AddProperty(RuntimeConstants.ENCODING_DEFAULT, "utf-8");engine.Init(prop);Stopwatch sw &#61; new Stopwatch();sw.Start();for (int i &#61; 0; i (){new Contact() { Name&#61;"Richie Liu", TotalOrderAmt&#61;180,EMail&#61;"RichieLiu-test&#64;gmail.com", Address&#61;"上海徐汇区钦州路" },new Contact() { Name&#61;"Kevin Zhang",TotalOrderAmt&#61;0, EMail&#61;"KevinZhang-test&#64;gmail.com", Address&#61;"苏州新区" },new Contact() { Name&#61;"Eric Wong", TotalOrderAmt&#61;626,EMail&#61;"EricWong-test&#64;gmail.com", Address&#61;"厦门海沧" },new Contact() { Name&#61;"RicCC", TotalOrderAmt&#61;2080,EMail&#61;"RicCC-test&#64;gmail.com", Address&#61;"上海徐汇区钦州路" }});context.Put("qryName", "Ric");context.Put("qryAddress", DateTime.Now);context.Put("hasMessage", true);context.Put("message", "This is a message from the server.");

context.Put("items1", new string[] { "AAA", "BBB", "CCC" });context.Put("items2", new List { new DateTime(1979, 1, 1), new DateTime(2010, 4, 1) });

IDictionary dic &#61; new Dictionary();dic.Add("AAA", 111M);dic.Add("BBB", 222M);dic.Add("CCC", 333M);context.Put("items3", dic);

DataTable table &#61; new DataTable();table.Columns.Add(new DataColumn("Key", typeof(string)));table.Columns.Add(new DataColumn("Value", typeof(int)));DataRow row &#61; table.NewRow();row["Key"] &#61; "item 1";row["Value"] &#61; 111;table.Rows.Add(row);row &#61; table.NewRow();row["Key"] &#61; "item 2";row["Value"] &#61; 222;table.Rows.Add(row);context.Put("items4", table);

if (!output){StringWriter writer &#61; new StringWriter();template.Merge(context, writer);writer.Close();}elsetemplate.Merge(context, HttpContext.Current.Response.Output);}public static long StringTemplateTest(int loops){Stopwatch sw &#61; new Stopwatch();sw.Start();for (int i &#61; 0; i
StringTemplate st &#61; group.LookupTemplate("contact_list");st.SetAttribute("contacts", new List(){new Contact() { Name&#61;"Richie Liu", TotalOrderAmt&#61;180,EMail&#61;"RichieLiu-test&#64;gmail.com", Address&#61;"上海徐汇区钦州路" },new Contact() { Name&#61;"Kevin Zhang",TotalOrderAmt&#61;0, EMail&#61;"KevinZhang-test&#64;gmail.com", Address&#61;"苏州新区" },new Contact() { Name&#61;"Eric Wong", TotalOrderAmt&#61;626,EMail&#61;"EricWong-test&#64;gmail.com", Address&#61;"厦门海沧" },new Contact() { Name&#61;"RicCC", TotalOrderAmt&#61;2080,EMail&#61;"RicCC-test&#64;gmail.com", Address&#61;"上海徐汇区钦州路" }});st.SetAttribute("qryName", "Ric");st.SetAttribute("qryAddress", DateTime.Now);st.SetAttribute("hasMessage", true);st.SetAttribute("message", "This is a message from the server.");

st.SetAttribute("items1", new string[] { "AAA", "BBB", "CCC" });st.SetAttribute("items2", new List { new DateTime(1979, 1, 1), new DateTime(2010, 4, 1) });

Dictionary dic &#61; new Dictionary();dic.Add("AAA", 111M);dic.Add("BBB", 222M);dic.Add("CCC", 333M);st.SetAttribute("items3", dic);

DataTable table &#61; new DataTable();table.Columns.Add(new DataColumn("Key1", typeof(string)));table.Columns.Add(new DataColumn("Value1", typeof(int)));DataRow row &#61; table.NewRow();row["Key1"] &#61; "item 1";row["Value1"] &#61; 111;table.Rows.Add(row);row &#61; table.NewRow();row["Key1"] &#61; "item 2";row["Value1"] &#61; 222;table.Rows.Add(row);st.SetAttribute("items4", table);

if (!output) st.ToString();else HttpContext.Current.Response.Write(st.ToString());}public static long ASPXTest(int loops){Stopwatch sw &#61; new Stopwatch();sw.Start();for (int i &#61; 0; i }
测试用的页面:


protected void Page_Load(object sender, EventArgs e)
{this.Response.Write("NVelocity: ");List times &#61; new List(5);times.Add(TemplateUtil.NVelocityTest(10000));times.Add(TemplateUtil.NVelocityTest(10000));times.Add(TemplateUtil.NVelocityTest(10000));times.Add(TemplateUtil.NVelocityTest(10000));times.Add(TemplateUtil.NVelocityTest(10000));TemplateUtil.WriteTime("Average Time: ", Convert.ToInt64(times.Average()));

this.Response.Write("

StringTemplate: ");times &#61; new List(5);times.Add(TemplateUtil.StringTemplateTest(1000));times.Add(TemplateUtil.StringTemplateTest(1000));times.Add(TemplateUtil.StringTemplateTest(1000));times.Add(TemplateUtil.StringTemplateTest(1000));times.Add(TemplateUtil.StringTemplateTest(1000));TemplateUtil.WriteTime("Average Time: ", Convert.ToInt64(times.Average()));

this.Response.Write("

ASP.NET: ");times &#61; new List(5);times.Add(TemplateUtil.ASPXTest(10000));times.Add(TemplateUtil.ASPXTest(10000));times.Add(TemplateUtil.ASPXTest(10000));times.Add(TemplateUtil.ASPXTest(10000));times.Add(TemplateUtil.ASPXTest(10000));TemplateUtil.WriteTime("Average Time: ", Convert.ToInt64(times.Average()));
}

NVelocity模板contact-list.vm如下:

姓名:地址:




Contact List



#foreach($c in $contacts)
#beforeall
#odd
#even
#each
#after
#afterall
姓名邮箱地址会员等级
$c.set_Name("$c.name - W") $c.get_Name()$c.EMail$c.Address#if($c.TotalOrderAmt>1000)钻卡会员#elseif($c.TotalOrderAmt>200)金卡会员#else Standard#end

#nodataNo contacts found!
#end



#if($hasMessage)
#set($msg&#61;"$message
--this message was append in NVelocity.")
$msg

#end




Item List - Array



#foreach($item in $items1)
#each$item
#between,
#end





Item List - List



#foreach($item in $items2)
#each$item.ToString("yyyy-MM-dd")
#between,
#end





Item List - Dictionary



#foreach($item in $items3)
#each
{ $item.Key - $item.Value }
#between
,#end





Item List - DataTable



#foreach($item in $items4.Rows)
{ $item.Key - $item.Value }
#between
,
#end

StringTemplate模板如下:
contact_list.st

姓名:地址:


$!this is a comment!$

Contact List



$contacts:row(class&#61;"list-odd"),row(class&#61;"list-even")$
姓名邮箱地址会员等级




$if(hasMessage)$
$message$ -
--this message was append in NVelocity.

$endif$




Item List - Array



$items1:{$attr$};separator&#61;","$





Item List - List



$items2:{$attr$};separator&#61;","$





Item List - Dictionary



$items3:{{ $it$ }};separator&#61;","$





Item List - DataTable



$items4.Rows:{{ $attr$ }};separator&#61;","$
row.st

$attr.Name$$attr.EMail$$attr.Address$
$if(attr.IsLevel3)$ 钻卡会员 $endif$
$if(attr.IsLevel2)$ 金卡会员 $endif$
$if(attr.IsLevel1)$ Standard $endif$
ASPNET.aspx页面:

姓名:&#39; />地址:&#39; />




Contact List



<%for (int i &#61; 0; i %>
<%}else{
%>
<%}
%>
<%}
%>
姓名邮箱地址会员等级
<% this.contacts[i].Name &#61; this.contacts[i].Name &#43; " - W"; %><%&#61; this.contacts[i].Name %>&#39;><%&#61; this.contacts[i].EMail %><%&#61; this.contacts[i].Address %><% if(this.contacts[i].TotalOrderAmt>1000){ %>钻卡会员<% }else if (this.contacts[i].TotalOrderAmt > 200){ %>金卡会员<%}else { %>Standard<% } %>




<% if (this.hasMessage){string msg &#61; this.message &#43; "
--this message was append in NVelocity.";%>
<%&#61; msg %>

<%} %>




Item List - Array



<% foreach(string s in this.items1){ %>
<%&#61; s %>,
<%} %>





Item List - List



<% foreach(DateTime dt in this.items2){ %>
<%&#61; dt.ToString("yyyy-MM-dd") %>,
<%} %>





Item List - Dictionary



<% foreach(System.Collections.Generic.KeyValuePair kv in this.items3){ %>
{<%&#61; kv.Key %>-<%&#61; kv.Value.ToString() %>},
<%} %>





Item List - DataTable



<% foreach(System.Data.DataRow row in this.items4.Rows ){ %>
{<%&#61; row["key"] %>-<%&#61; row["value"]%>},
<%} %>
ASPNET.aspx.cs:


public string qryName;
public string qryAddress;
public IList contacts;
public bool hasMessage;
public string message;
public string[] items1;
public List items2;
public IDictionary items3;
public DataTable items4;


protected void Page_Load(object sender, EventArgs e)
{if (!IsPostBack){this.qryName &#61; "Ric";this.qryAddress &#61; DateTime.Now.ToString();this.hasMessage &#61; true;this.message &#61; "This is a message from the server.";this.contacts &#61; new List(){new Contact() { Name&#61;"Richie Liu", TotalOrderAmt&#61;180,EMail&#61;"RichieLiu-test&#64;gmail.com", Address&#61;"上海徐汇区钦州路" },new Contact() { Name&#61;"Kevin Zhang",TotalOrderAmt&#61;0, EMail&#61;"KevinZhang-test&#64;gmail.com", Address&#61;"苏州新区" },new Contact() { Name&#61;"Eric Wong", TotalOrderAmt&#61;626,EMail&#61;"EricWong-test&#64;gmail.com", Address&#61;"厦门海沧" },new Contact() { Name&#61;"RicCC", TotalOrderAmt&#61;2080,EMail&#61;"RicCC-test&#64;gmail.com", Address&#61;"上海徐汇区钦州路" }};this.items1 &#61; new string[] { "AAA", "BBB", "CCC" };this.items2 &#61; new List {new DateTime(1979, 1, 1), new DateTime(2010, 4, 1) };this.items3 &#61; new Dictionary();this.items3.Add("AAA", 111M);this.items3.Add("BBB", 222M);this.items3.Add("CCC", 333M);DataTable table &#61; new DataTable();table.Columns.Add(new DataColumn("Key", typeof(string)));table.Columns.Add(new DataColumn("Value", typeof(int)));DataRow row &#61; table.NewRow();row["Key"] &#61; "item 1";row["Value"] &#61; 111;table.Rows.Add(row);row &#61; table.NewRow();row["Key"] &#61; "item 2";row["Value"] &#61; 222;table.Rows.Add(row);this.items4 &#61; table;}
}

转:https://www.cnblogs.com/RicCC/archive/2010/04/03/nvelocity-vs-stringtemplate-performance.html



推荐阅读
  • 本文介绍了深入浅出Linux设备驱动编程的重要性,以及两种加载和删除Linux内核模块的方法。通过一个内核模块的例子,展示了模块的编译和加载过程,并讨论了模块对内核大小的控制。深入理解Linux设备驱动编程对于开发者来说非常重要。 ... [详细]
  • 本文介绍了如何使用Express App提供静态文件,同时提到了一些不需要使用的文件,如package.json和/.ssh/known_hosts,并解释了为什么app.get('*')无法捕获所有请求以及为什么app.use(express.static(__dirname))可能会提供不需要的文件。 ... [详细]
  • Java自带的观察者模式及实现方法详解
    本文介绍了Java自带的观察者模式,包括Observer和Observable对象的定义和使用方法。通过添加观察者和设置内部标志位,当被观察者中的事件发生变化时,通知观察者对象并执行相应的操作。实现观察者模式非常简单,只需继承Observable类和实现Observer接口即可。详情请参考Java官方api文档。 ... [详细]
  • gitlab重置password
    ruby没怎么学,自己搭建的gitlab的rootpassword又忘了。幸好看见此帖子,试验okhttp:roland.kierkels.netgitreset-your-git ... [详细]
  • 2018-02-1420:07:13,610ERROR[main]regionserver.HRegionServerCommandLine:Regionserverexiting ... [详细]
  • --获取有关按平均CPU时间排在最前面的五个查询的信息SELECTTOP5total_worker_timeexecution_countAS,SUBSTRING(st.text, ... [详细]
  • Java面向对象8常用类2(MathString)
    Math1、直接使用,无需导包packagejava.lang;2、final修饰类不能被继承publicfinalclassMath3、构造器私有化ÿ ... [详细]
  • 本文介绍了解决java开源项目apache commons email简单使用报错的方法,包括使用正确的JAR包和正确的代码配置,以及相关参数的设置。详细介绍了如何使用apache commons email发送邮件。 ... [详细]
  • substring( ) 和 substr( ) 的区别
    1、里面的参数定义不一样substring(x,y)substr(x,y);substring里面的x,y是位置,相当于坐标,substr里的x是位置,y是长度length特殊备注 ... [详细]
  • mysql  GROUP_CONCAT获取分组的前几名
    如果是oracle应该很容易用Partition By实现。比如说要获取班级的前3名,就可以用GROUP_CONCAT+ GROUPBY + substring_index实现。考 ... [详细]
  • PreparedStatement防止SQL注入
    添加数据:packagecom.hyc.study03;importcom.hyc.study02.utils.JDBCUtils;importjava.sql ... [详细]
  • php设置数组大小_【大厂必备】2020超经典PHP面试题
    结合我自己这段时间的面试情况,面对的一些php面试题列举出来,基本上结合自己的看法回答的,不妥的地方请大家指出去,与大家一起 ... [详细]
  • ***Createdbyjiachenpanon161118.**合法uri*exportfunctionvalidateURL(textval){consturlregex^( ... [详细]
  • destoon会员注册提示“数据校验失败(2)”解决方法【PHP】
    后端开发|php教程destoon,会员注册,数据校验失败,后端开发-php教程很多人在使用destoon建立一个B2B系统的时候,会在企业站注册企业用户的时候出现:“数据校验失败 ... [详细]
  • 摘要:本文从介绍基础概念入手,探讨了在CC++中对日期和时间操作所用到的数据结构和函数,并对计时、时间的获取、时间的计算和显示格式等方面进行了阐述。本文还通过大量的实例向你展示了t ... [详细]
author-avatar
C3calm_daidai_649
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有