您的位置:首页 > 其它

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)

测试用的项目文件: 下载

测试辅助类:
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;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: