Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stringtemplate low performance in comparison to Velocity and Mvel

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  
like image 433
Roman K Avatar asked Oct 09 '22 08:10

Roman K


1 Answers

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);
    }   
}   
like image 131
Terence Parr Avatar answered Oct 13 '22 12:10

Terence Parr