I am trying to do some evaluation of template frameworks.
For a simple performance test I'm using these templates
private static String mvelTemplate = "Hello, my name is @{name},"
+ " @foreach{user : group.users} - @{user.id} - @{user.name} "
+ " @end{}";
private static String velocityTemplate = "Hello, my name is ${name},"
+ "#foreach($user in $group.users) - ${user.id} - ${user.name} #end " ;
private static String stringTemplate = "Hello, my name is <name>,"
+ "<group.users:{x| - <x.id> - <x.name>}> ";
// the group has 20 users
// 'Java' uses plain StringBuffer
The part of Stringtemplate is
ST st = new ST(stringTemplate);
for (Map.Entry<String, Object> entry : vars.entrySet()) {
st.add(entry.getKey(),entry.getValue());
}
start = System.currentTimeMillis();
for (int n = 0; n < 10000; n ++) {
st.render();
}
end = System.currentTimeMillis();
And the results are
Mvel.Compiled elapsed:68ms. ~147K per second
Velocity Cache elapsed:183ms. ~54K per second
StringTemplate elapsed:234ms. ~42K per second
Java elapsed:21ms. ~476K per second
Since I have no idea of string template, here is my question:
Is StringTemplate really that slow or is there an other (faster) way to render a template with it.
Update:
vars looks like this:
Map<String,Object> vars = new HashMap<String,Object>();
Group g = new Group("group1");
for (int i = 0; i < 20; i++) {
g.addUser(new User(i, "user" + i));
}
vars.put("group", g);
vars.put("name", "john");
now with 1.000.000 iterations per template and looped the whole benchmark 10 times
Mvel.Compiled elapsed:7056ms. ~141K per second
Velocity Cache elapsed:18239ms. ~54K per second
StringTemplate elapsed:22926ms. ~43K per second
Java elapsed:2182ms. ~458K per second
part of what you are observing is likely a compiler warm-up issue. When I run the test I enclose below 10000, it takes 350ms on my computer. when I increased to 100,000 it takes 1225ms, which is only 3.5x more time not 10x more time. when I run it 1,000,000 I get 8397ms which is only about 7x the cost and time when it should be 10x. Clearly the compiler is doing something interesting here with optimization. For a long-running program, I would expect ST to do better in your tests. The garbage collector could also be doing something here. Try your examples with bigger loop lengths.
Anyway, speed was not my first priority with ST v4, but thank you for pointing this out. I will probably look into optimizing at some point. I don't think I've even run a profiler on it.
import org.stringtemplate.v4.*;
import java.util.*;
public class T {
public static class User {
public int id;
public String name;
public User(int id, String name) {
this.id= id;
this.name = name;
}
}
private static String stringTemplate = "Hello, my name is <name>,"
+ "<users:{x| - <x.id> - <x.name>}> ";
public static void main(String[] args) {
ST st = new ST(stringTemplate);
List<User> users = new ArrayList<User>();
for (int i=1; i<=5; i++) {
users.add(new User(i, "bob"+i));
}
st.add("users", users);
st.add("name", "tjp");
long start = System.currentTimeMillis();
for (int n = 0; n < 1000000; n ++) {
st.render();
}
long end = System.currentTimeMillis();
System.out.printf("%d ms\n", end-start);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With