NVelocity 1.1 vs StringTemplate 3.2
2010-04-03 01:50
239 查看
拿NVelocity 1.1、StringTemplate 3.2和ASP.NET的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)
测试用的项目文件: 下载
测试辅助类:
测试用的页面:
NVelocity模板contact-list.vm如下:
StringTemplate模板如下:
contact_list.st
row.st
结果就是,在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)
测试用的项目文件: 下载
测试辅助类:
context.Put("items1", new string[] { "AAA", "BBB", "CCC" }); context.Put("items2" , new List<DateTime> { new DateTime(1979, 1, 1), new DateTime(2010, 4, 1) }); IDictionary<string, decimal> dic = new Dictionary<string, decimal>(); dic.Add("AAA", 111M); dic.Add("BBB", 222M); dic.Add("CCC", 333M); context.Put("items3", dic); DataTable table = new DataTable(); table.Columns.Add(new DataColumn("Key", typeof(string))); table.Columns.Add(new DataColumn("Value", typeof(int))); DataRow row = table.NewRow(); row["Key"] = "item 1"; row["Value"] = 111; table.Rows.Add(row); row = table.NewRow(); row["Key"] = "item 2"; row["Value"] = 222; table.Rows.Add(row); context.Put("items4", table); if (!output) { StringWriter writer = new StringWriter(); template.Merge(context, writer); writer.Close(); } else template.Merge(context, HttpContext.Current.Response.Output); } public static long StringTemplateTest(int loops) { Stopwatch sw = new Stopwatch(); sw.Start(); for (int i = 0; i < loops; i++) StringTemplateParse(i, false); sw.Stop(); WriteTime("Total Elapsed Time: ", sw.ElapsedMilliseconds); return sw.ElapsedMilliseconds; } public static void StringTemplateParse(int loop, bool output) { StringTemplateGroup group = new StringTemplateGroup("stperf", ST_ROOT_PATH); StringTemplate st = group.LookupTemplate("contact_list"); st.SetAttribute("contacts", new List<Contact>() { new Contact() { Name="Richie Liu", TotalOrderAmt=180, EMail="RichieLiu-test@gmail.com", Address="上海徐汇区钦州路" }, new Contact() { Name="Kevin Zhang",TotalOrderAmt=0, EMail="KevinZhang-test@gmail.com", Address="苏州新区" }, new Contact() { Name="Eric Wong", TotalOrderAmt=626, EMail="EricWong-test@gmail.com", Address="厦门海沧" }, new Contact() { Name="RicCC", TotalOrderAmt=2080, EMail="RicCC-test@gmail.com", Address="上海徐汇区钦州路" } }); 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<DateTime> { new DateTime(1979, 1, 1), new DateTime(2010, 4, 1) }); Dictionary<string, decimal> dic = new Dictionary<string, decimal>(); dic.Add("AAA", 111M); dic.Add("BBB", 222M); dic.Add("CCC", 333M); st.SetAttribute("items3", dic); DataTable table = new DataTable(); table.Columns.Add(new DataColumn("Key1", typeof(string))); table.Columns.Add(new DataColumn("Value1", typeof(int))); DataRow row = table.NewRow(); row["Key1"] = "item 1"; row["Value1"] = 111; table.Rows.Add(row); row = table.NewRow(); row["Key1"] = "item 2"; row["Value1"] = 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 = new Stopwatch(); sw.Start(); for (int i = 0; i < loops; i++) ASPXParse(i); sw.Stop(); WriteTime("Total Elapsed Time: ", sw.ElapsedMilliseconds); return sw.ElapsedMilliseconds; } public static void ASPXParse(int loop) { StringWriter writer = new StringWriter(); HttpContext.Current.Server.Execute("ASPNET.aspx", writer); writer.Close(); } }
测试用的页面:
this.Response.Write("< br />< br />StringTemplate: "); times = new List<long>(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("< br />< br />ASP.NET: "); times = new List<long>(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如下:
<h2>Contact List</h2> <div class="contact-list"> #foreach($c in $contacts) #beforeall <table> <tr class="list-header"> <td>姓名</td> <td>邮箱</td> <td>地址</td> <td>会员等级</td> </tr> #odd <tr class="list-odd"> #even <tr class="list-even"> #each <td>$c.set_Name("$c.name - W") $c.get_Name()</td> <td><a href="mailto:$c.EMail">$c.EMail</a></td> <td>$c.Address</td> <td>#if($c.TotalOrderAmt>1000)钻卡会员 #elseif($c.TotalOrderAmt>200)金卡会员 #else Standard#end</td> #after </tr> #afterall </table> #nodata No contacts found! #end </div> #if($hasMessage) #set($msg="$message < br />--this message was append in NVelocity.") <div class="message">$msg</div> #end < br /> <h2>Item List - Array</h2> <div> #foreach($item in $items1) #each $item #between , #end </div> < br /> <h2>Item List - List</h2> <div> #foreach($item in $items2) #each $item.ToString("yyyy-MM-dd") #between , #end </div> < br /> <h2>Item List - Dictionary</h2> <div> #foreach($item in $items3) #each { $item.Key - $item.Value } #between ,#end </div> < br /> <h2>Item List - DataTable</h2> <div> #foreach($item in $items4.Rows) { $item.Key - $item.Value } #between , #end </div>
StringTemplate模板如下:
contact_list.st
$if(hasMessage)$ <div class="message">$message$ - < br />--this message was append in NVelocity.</div> $endif$ < br /> <h2>Item List - Array</h2> <div> $items1:{$attr$};separator=","$ </div> < br /> <h2>Item List - List</h2> <div> $items2:{$attr$};separator=","$ </div> < br /> <h2>Item List - Dictionary</h2> <div> $items3:{{ $it$ }};separator=","$ </div> < br /> <h2>Item List - DataTable</h2> <div> $items4.Rows:{{ $attr$ }};separator=","$ </div>
row.st
ASPNET.aspx页面:<div class="query-form"> <table> <tr> <td>姓名:</td> <td><input type="text" id="txtQryName" class="text" value='<%= this.qryName %>' /></td> <td>地址:</td> <td><input type="text" id="txtQryAddress" class="text" value='<%= this.qryAddress %>' /></td> <td><input type="button" id="btnQuery" value="查询" /></td> </tr> </table> </div> <h2>Contact List</h2> <div class="contact-list"> <table> <tr class="list-header"> <td>姓名</td> <td>邮箱</td> <td>地址</td> <td>会员等级</td> </tr> <% for (int i = 0; i < this.contacts.Count; i++) { if ((i + 1) % 2 == 1) { %> <tr class="list-odd"> <% } else { %> <tr class="list-even"> <% } %> <td><% this.contacts[i].Name = this.contacts[i].Name + " - W"; %><%= this.contacts[i].Name %></td> <td><a href='<%= this.contacts[i].EMail %>'><%= this.contacts[i].EMail %></a></td> <td><%= this.contacts[i].Address %></td> <td><% if(this.contacts[i].TotalOrderAmt>1000){ %>钻卡会员 <% } else if (this.contacts[i].TotalOrderAmt > 200) { %>金卡会员 <%} else { %>Standard<% } %></td> </tr> <% } %> </table> </div> <% if (this.hasMessage) { string msg = this.message + "< br />--this message was append in NVelocity."; %> <div class="message"><%= msg %></div> <%} %> < br /> <h2>Item List - Array</h2> <div> <% foreach(string s in this.items1){ %> <%= s %>, <%} %> </div> < br /> <h2>Item List - List</h2> <div> <% foreach(DateTime dt in this.items2){ %> <%= dt.ToString("yyyy-MM-dd") %>, <%} %> </div> < br /> <h2>Item List - Dictionary</h2> <div> <% foreach(System.Collections.Generic.KeyValuePair<string, decimal> kv in this.items3){ %> {<%= kv.Key %>-<%= kv.Value.ToString() %>}, <%} %> </div> < br /> <h2>Item List - DataTable</h2> <div> <% foreach(System.Data.DataRow row in this.items4.Rows ){ %> {<%= row["key"] %>-<%= row["value"]%>}, <%} %> </div>
ASPNET.aspx.cs:
public string qryName;
public string qryAddress;
public IList<Contact> contacts;
public bool hasMessage;
public string message;
public string[] items1;
public List<DateTime> items2;
public IDictionary<string, decimal> items3;
public DataTable items4;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
this.qryName = "Ric";
this.qryAddress = DateTime.Now.ToString();
this.hasMessage = true;
this.message = "This is a message from the server.";
this.contacts = new List<Contact>()
{
new Contact() {
Name="Richie Liu", TotalOrderAmt=180,
EMail="RichieLiu-test@gmail.com",
Address="上海徐汇区钦州路" },
new Contact() {
Name="Kevin Zhang",TotalOrderAmt=0,
EMail="KevinZhang-test@gmail.com",
Address="苏州新区" },
new Contact() {
Name="Eric Wong", TotalOrderAmt=626,
EMail="EricWong-test@gmail.com",
Address="厦门海沧" },
new Contact() {
Name="RicCC", TotalOrderAmt=2080,
EMail="RicCC-test@gmail.com",
Address="上海徐汇区钦州路" }
};
this.items1 = new string[] { "AAA", "BBB", "CCC" };
this.items2 = new List<DateTime> {
new DateTime(1979, 1, 1),
new DateTime(2010, 4, 1) };
this.items3 = new Dictionary<string, decimal>();
this.items3.Add("AAA", 111M);
this.items3.Add("BBB", 222M);
this.items3.Add("CCC", 333M);
DataTable table = new DataTable();
table.Columns.Add(new DataColumn("Key", typeof(string)));
table.Columns.Add(new DataColumn("Value", typeof(int)));
DataRow row = table.NewRow();
row["Key"] = "item 1";
row["Value"] = 111;
table.Rows.Add(row);
row = table.NewRow();
row["Key"] = "item 2";
row["Value"] = 222;
table.Rows.Add(row);
this.items4 = table;
}
}
相关文章推荐
- opencv3.2在vs2015开发环境搭建+cmake3.8编译生成opencv x86版本库
- VS2015下VOpenCV3.2 +Kinect V2 环境配置
- vs-安装了vs但是提示我的framework不是1.1的,但是我的就是1.1的
- Vs .NET 已检测到指定的 Web 服务器运行的不是 ASP.NET 1.1 版
- "VS.NET Web服务器运行的不是ASP.NET 1.1 版"的解决办法
- VisualStudio工程设置(二)---opencv3.2在vs2015开发环境搭建+cmake3.8编译生成opencv x86版本库
- cocos2dx 3.2从零学习(六)——CocosStudio(VS2013工程导入及环境设置)
- http/0.9 http/1.0 vs http/1.1
- 关于cocos2d-x-3.2版本环境的搭建和在VS环境下自己创建工程的步骤
- vs2015配置opencv3.2
- win7运行第一个opencv程序,基于opencv3.2,官方vc14编译版本,QT5.8 VS2015平台
- vs.net中创建asp.net程序时,出现:http/1.1 500 internal server error
- VS2017 创建的 ASP.NET Core 1.1 Web 项目 发布的IIS7提示“HTTP Error 502.5 - Process Failure”
- VS 2003 打开/开发 网站项目时报错:“http/1.1. 400 bad request”
- HTTP1.0 VS HTTP1.1
- 稠密特征的光流opencv3.2+VS
- VS Code从零开始开发调试.NET Core 1.1
- Windows下 OpenCV 3.2配置和在VS2015下的简单demo
- Win10 中VS2015 配置opencv3.2
- 人脸识别(VS2015+opencv3.2的配置)