NVelocity 1.1 vs StringTemplate 3.2

Source: Internet
Author: User
Take the NVelocity 1.1, StringTemplate 3.2, and ASP. net aspx pages for a performance test comparison. The comparison results are as follows:

The result is that, on two different machines, ASPX: StringTemplate: NVelocity is 1.00: 8.53: 1.61 and 1.00: 7.34: 1.71, respectively. StringTemplate has the lowest performance, NVelocity is a bit close to the parsing efficiency of ASPX. The following points are also found during the test:
1. For StringTemplate, StringTemplateGroup should not be used consecutively too many times. The performance of creating a StringTemplateGroup for each task is much better.
2. in some previous versions, the same StringTemplateGroup object is used repeatedly to obtain the template. This causes serious memory leakage and poor performance. In version 3.2, the performance is much better and there is no memory leakage.
3. There are also some bugs in StringTemplate, such as the Dictionary and DataTable in the following list tests. The value cannot be read in version 3.2 (Version 3.1 can read the DataTable in the list)
Project files for testing: Download

Test helper class:

Using System; using System. collections; using System. collections. generic; using System. data; using System. diagnostics; using System. IO; using System. web; using antl3.st; using Commons. collections; 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 does not support comparison and judgment in the template. Therefore, public bool IsLevel3 {get {return this. totalOrderAmt> 1000 ;}} public bool IsLevel2 {get {return this. totalOrderAmt <= 1000 & this. totalOrderAmt> 200 ;}} public bool IsLevel1 {get {return this. totalOrderAmt <= 200 ;}}}
Public class TemplateUtil {private static string ST_ROOT_PATH = string. empty; static TemplateUtil () {string rootDir = HttpContext. current. server. mapPath (". /st "); if (rootDir. endsWith ("\") rootDir = rootDir. substring (0, rootDir. length-1); ST_ROOT_PATH = rootDir;} public static void WriteTime (string title, long time) {HttpContext. current. response. write ("<br/>" + title); long millisecondes = time % 1000; long minutes = time/1000/60; long seconds = (time-minutes * 60*1000) /1000; if (minutes> 0) HttpContext. current. response. write (minutes. toString () + "m,"); if (seconds> 0) HttpContext. current. response. write (seconds. toString () + "s,"); HttpContext. current. response. write (millisecondes. toString () + "ms");} public static long NVelocityTest (int loops) {VelocityEngine engine = new VelocityEngine (); ExtendedProperties prop = 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 = new Stopwatch (); sw. start (); for (int I = 0; I <loops; I ++) NVelocityParse (engine, I, false); sw. stop (); WriteTime ("Total Elapsed Time:", sw. elapsedMilliseconds); return sw. elapsedMilliseconds;} public static void NVelocityParse (VelocityEngine engine, int loop, bool output) {Template template = engine. getTemplate ("contact-list.vm"); VelocityContext context = new VelocityContext (); context. put ("contacts", new List <Contact> () {new Contact () {Name = "Richie Liu", TotalOrderAmt = 180, EMail = "RichieLiu-test@gmail.com ", address = "Qinzhou Road, Xuhui District, Shanghai"}, new Contact () {Name = "Kevin Zhang", TotalOrderAmt = 0, EMail = "KevinZhang-test@gmail.com", Address = "Suzhou new District "}, new Contact () {Name = "Eric Wong", TotalOrderAmt = 626, EMail = "EricWong-test@gmail.com", Address = "Xiamen Haicang"}, new Contact () {Name = "RicCC", TotalOrderAmt = 2080, EMail = "RicCC-test@gmail.com", Address = "Qinzhou Road, Xuhui District, Shanghai"}); 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 <DateTime> {new DateTime (1979, 1, 1), new DateTime (2010, 4, 1 )});
IDictionary <string, decimal> dic = new Dictionary <string, decimal> (); dic. add ("AAA", 111 M); dic. add ("BBB", 222 M); dic. add ("CCC", 333 M); 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 = "Qinzhou Road, Xuhui District, Shanghai"}, new Contact () {Name = "Kevin Zhang", TotalOrderAmt = 0, EMail = "KevinZhang-test@gmail.com", Address = "Suzhou new District "}, new Contact () {Name = "Eric Wong", TotalOrderAmt = 626, EMail = "EricWong-test@gmail.com", Address = "Xiamen Haicang"}, new Contact () {Name = "RicCC", TotalOrderAmt = 2080, EMail = "RicCC-test@gmail.com", Address = "Qinzhou Road, Xuhui District, Shanghai"}); 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", 111 M); dic. add ("BBB", 222 M); dic. add ("CCC", 333 M); 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 ();}}

Test page:

protected void Page_Load(object sender, EventArgs e){    this.Response.Write("NVelocity: ");    List<long> times = new List<long>(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("< 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 template contact-list.vm is as follows:

<Div class = "query-form"> <table> <tr> <td> Name: </td> <input type = "text" id = "txtQryName" class = "text" value = "$ qryName"/> </td> <td> address: </td> <input type = "text" id = "txtQryAddress" class = "text" value = "$ qryAddress"/> </td> <input type = "button" id = "btnQuery" value = "query"/> </td> </tr> </table> </div>
<H2> Contact List # If ($ hasMessage) # set ($ msg = "$ message <br/> -- this message was append in NVelocity. ") <div class =" message "> $ msg </div> # end
<Br/> <Br/> <Br/> <Br/>

The StringTemplate template is as follows:
Contact_list.st

<Div class = "query-form"> <table> <tr> <td> Name: </td> <input type = "text" id = "txtQryName" class = "text" value = "$ qryName $"/> </td> <td> address: </td> <input type = "text" id = "txtQryAddress" class = "text" value = "$ qryAddress $"/> </td> <td> <input type = "button" id = "btnQuery" value = "query"/> </td> </tr> </table> </div> $! This is a comment! $ <H2> Contact List $ If (hasMessage) $ <div class = "message"> $ message $-<br/> -- this message was append in NVelocity. </div> $ endif $
<Br/> <Br/> <Br/> <Br/>

Row. st

<Tr class = "$ class $"> <td> $ attr. name $ </td> <a href = "mailto: $ attr. EMail $ "> $ attr. EMail $ </a> </td> <td> $ attr. address $ </td> <td> $ if (attr. isLevel3) $ drill card member $ endif $ if (attr. isLevel2) $ gold card member $ endif $ if (attr. isLevel1) $ Standard $ endif $ </td> </tr>

ASPNET. aspx page:

<Div class = "query-form"> <table> <tr> <td> Name: </td> <input type = "text" id = "txtQryName" class = "text" value = '<% = this. qryName %> '/> </td> <td> address: </td> <input type = "text" id = "txtQryAddress" class = "text" value = '<% = this. qryAddress %> '/> </td> <input type = "button" id = "btnQuery" value = "query"/> </td> </tr> </table> </div>
<H2> Contact List <% If (this. hasMessage) {string msg = this. message + "<br/> -- this message was append in NVelocity. "; %> <div class =" message "> <% = msg %> </div> <%} %>
<Br/> <Br/> <Br/> <Br/>

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 = "Qinzhou Road, Xuhui District, Shanghai"}, new Contact () {Name = "Kevin Zhang", TotalOrderAmt = 0, EMail = "KevinZhang-test@gmail.com", Address = "Suzhou new District "}, new Contact () {Name = "Eric Wong", TotalOrderAmt = 626, EMail = "EricWong-test@gmail.com", Address = "Xiamen Haicang"}, new Contact () {Name = "RicCC", TotalOrderAmt = 2080, EMail = "RicCC-test@gmail.com", Address = "Qinzhou Road, Xuhui District, Shanghai" }}; 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", 111 M); this. items3.Add ("BBB", 222 M); this. items3.Add ("CCC", 333 M); 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 ;}}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.