`
javatar
  • 浏览: 1704732 次
  • 性别: Icon_minigender_1
  • 来自: 杭州699号
社区版块
存档分类
最新评论

比Velocity快10倍的模板引擎

阅读更多
在07年的时候,写过一个模板引擎,当时叫CommonTemplate,以前JavaEye有个开源系列介绍:http://www.iteye.com/news/3381,后来功能越来越多,性能却越来越差,在金大为发给我性能对比结果后,看到惨不忍睹的差距,就打算抛弃原设计进行重写,但因工作忙,就搁置了,最近看温少发了几个EL和JSON的解析器,有点手痒,就抽了个周未,拿出来再改了改,主要将模板改成了字节码编译,并简化了语法及缩小使用范围,只针对HTML场景使用,并将名称改成了HTTL,名字含义是把HTML中的M(Marker)改成了T(Template),放在GoogleCode上:http://code.google.com/p/httl,性能和Java硬编码输出模板内容差不多,比Velocity/FreeMarker等快10倍左右。

语法方面的区别:
发现基于文本指令的,基于HTML标签的,基于HTML注释的,都有不少模板引擎实现,
为了标新立异以及使用的直观性,HTTL采用基于HTML属性的指令,如:
<table if="user.role == 'admin'">
    <tr foreach="book in books">
        <td>${book.title}</td>
    </tr>
</table>


选型方面的区别:
  • Velocity采用JavaCC编译成AST树,解释执行。
  • FreeMarker类似,只是采用FreeCC。
  • Smarty4j采用ASM生成字节码,对条件等字节码的生成比JDK稍逊,而且需在运行时判断context变量的类型,无法强类型编译模板。
  • HTTL采用先将模板转译成Java代码,再由JDK或Javassist编译成字节码,并在模板上声明传入类型,在编译期就推演所有变量类型,减少反射和运行时类型判断。

  • 部分优化策略示例:

    (1) 强类型编译
    对于表达式${user.name}的编译:
    Smarty4j弱类型字节码生成:
    Object user = context.get("user"); // 无法确定user是Map还是POJO
    // 反射获取属性的值,而且要运行期判断是user.getName(),还是user.name字段
    Object name = ReflectUtil.get(user, "name"); // 接下来name也要反射
    

    Httl强类型字节码生成:
    User user = (User)context.get("user"); // 通过in="User user"声明类型
    String name = user.getName(); // 编译期通过User的字段类型推演name的类型,并在编译期决定使用getName()
    

    如果只是编译成弱类型字节码,性能比解释执行快不了多少,淘宝编译Velocity的测试数据显示,只能比JavaCC的AST解释执行快10%左右,参见附件的PPT。(附件的PPT是蒋江涛在InfoQ大会的演讲稿,是公开的)

    (2) 对大模板拆分子函数:(未发布)
    SunJDK缺省对大于5K字节码的方法不进行JIT优化,
    所以当模板的内容较大时,会导致生成的字节码也比较大,
    通过拆分子函数,可以解决JIT优化问题。
    淘宝编译Velocity的测试数据显示,大模板拆分成小模板性能提升35%,参见附件的PPT。

    (3) 编译时就将文本编译成字节,加快输出:
    原编译:
    writer.write("<table><tr><td>");
    writer.write(user.getName());
    

    改为编译成:
    output.write( new byte[] {60, 116, 97, 98, 108, 101, 62, 60, 116, 114, 62, 60, 116, 100, 62};);
    output.write(user.getName().getBytes());
    

    淘宝编译Velocity的测试数据显示,将String输出预编译为byte[]输出,性能提升50%,参见附件的PPT。

    (4) 对同条件if语句优化:(未发布)
    if (user.role == "admin") {
        // ...
    } else if (user.role == "member") {
        // ...
    } else {
        // ...
    }
    

    优化后:
    int id = System.identityHashCode(user.role);
    switch (id) {
        case 3452345: // 编译时计算"admin"的identityHashCode
        // ...
        case 2342452:  // 编译时计算"member"的identityHashCode
        // ...
        default: 
        // ...
    }
    


    (5) 对于赋值生成的price为局部变量,不put回context:
    比如:set="price = price * discount / 100"编译:
    int price = price * discount / 100;
    

    除非声明out="price",才在模板渲染最后:
    context.put("price", price);
    


    (6) 减少int到Integer等元类型的boxed和unboxed,以及instanceof。
    因为模板输出的大量是基本类型和字符串,
    比如当输出基本类型时,需要转成String,如果使用format(Object)接口,就会将基本类型装箱,
    Httl遇到任何类似需要boxed和unboxed的地方,都会重载所有基本类型方法,以减少boxed和unboxed的处理。
    出现instanceof的地方也一样,会尽量多态处理。

    (7) 所有编译过程都会保持和计算源码位置,
    当出错时,错误信息能准确定位到出错行列。

    等等。

    性能测试:
  • 模板内循环显示100行数据。
  • 每模板各运行一万次。
  • 模板大小约800字符。
  • 模板每次运行输出内容约27K字符。
  • 测试类:PerformanceTest.java

  • 测试结果:
    Engine 编译时间 运行一万次时间 每秒处理数 模板 测试类
    Freemarker 125ms 16,934ms 590t/s books.ftl FreemarkerCase.java
    Velocity 110ms 19,278ms 518t/s books.vm VelocityCase.java
    Smarty4j 78ms 21,653ms 461t/s books.st Smarty4jCase.java
    Httl 547ms 2,077ms 4,814t/s books.httl HttlCase.java
    Java 0ms 2,016ms 4,960t/s Books.java JavaCase.java

    测试代码:
    http://code.google.com/p/httl/downloads/list

    更多信息参见:
    http://code.google.com/p/httl

    HTTL缺省使用Jdk的javax,tools编译字节码,需要500ms左右,如果换成Javassist编译,编译时间可以降到200ms左右,但字节码执行效率略差一点,但每个模板只编译一次,所以编译慢点也能忍受,如果想换成Javassist,只需在httl.properties中加入:
    compiler=com.googlecode.httl.support.compilers.JavassistCompiler
    java.version=1.4
    

    注:Javassist不支持1.5的语法,所以要设置java.version=1.4
    分享到:
    评论
    4 楼 greenlaw110 2013-02-02  
    这里有个java template benchmark程序。大家可以下载下来直接run ant。这是按照一个很通常的web应用场景写的,httl的确是最快的,但是不能说在正常的应用场合会快10倍。
    3 楼 zhglhy 2013-01-14  
    多谢分享,学习了!
    2 楼 liberD 2011-09-15  
    对了,支持楼主!希望以后向您多学习!
    1 楼 liberD 2011-09-15  
    很好很牛叉!但是不知道是否比FreeMarker更通用。

    相关推荐

      Velocity模板引擎Velocity模板引擎

      Velocity模板引擎Velocity模板引擎Velocity模板引擎Velocity模板引擎Velocity模板引擎Velocity模板引擎Velocity模板引擎Velocity模板引擎Velocity模板引擎Velocity模板引擎

      velocity开发包vm模板引擎

      Velocity是一款强大的Java模板引擎,由Apache软件基金会开发并维护,它是Apache Jakarta项目的一部分。 Velocity的主要设计目标是将表现层逻辑从应用逻辑中分离出来,使开发者可以专注于业务逻辑的实现,而无需关心...

      JavaScript模板引擎Velocity.js.zip

      Velocity 是基于Java的模板引擎,广泛应用在阿里集 体各个子公司。Velocity模板适用于大量模板使用的场景,支持复杂的逻辑运算,包含 基本数据类型、变量赋值和函数等功能。Velocity.js 支持 Node.js 和浏览器环境。...

      Velocity--java的模板引擎

      **Velocity——Java的模板引擎** Velocity是Apache软件基金会下的一个开源项目,它是一个基于Java的模板引擎,专门用于生成动态Web内容。Velocity的目标是将HTML、XML等模板语言与业务逻辑分离,使得开发者可以专注...

      SpringBoot Velocity 代码生成模板

      在Spring Boot项目中,利用Velocity模板引擎,我们可以创建一系列模板文件,如Mapper、Mapper.xml、Service和Controller等,这些模板在运行时会根据数据库中的表结构动态生成对应的Java源码。这不仅避免了手动编写...

      Velocity模板引擎技术在Java Web中的应用.pdf

      "Velocity模板引擎技术在Java Web中的应用" Velocity模板引擎技术是Java Web开发中的一种重要技术,旨在解决Java Web页面视图和业务逻辑的耦合问题。通过使用Velocity模板引擎技术,可以将Java Web页面视图和业务...

      velocity模板引擎

      Velocity模板引擎为Java Web开发提供了强大且灵活的功能支持。通过上述知识点的学习,我们可以了解到Velocity的基本用法,包括变量定义、循环、条件判断、格式化、国际化支持等方面的内容。这些知识点是使用Velocity...

      Java进阶教程Velocity快速掌握模板引擎视频

      本课程从velocity engine也就是velocity引擎开始, 先讲解velocity的基本使用以及基础语法 , 然后再讲解velocity 的进阶内容velocity Tools , 以及velocity作为web项目的视图改如何使用 , 每一部分都会有一个综合案例...

      velocity实现邮件模板定制

      在IT行业中,Velocity是一个强大的模板引擎,常用于生成动态内容,比如HTML页面、电子邮件模板定制等。本篇文章将深入探讨如何使用Velocity实现邮件模板的定制,以及与之相关的源码和工具。 首先,Velocity的基本...

      Velocity_中文手册

      在实现具体的页面动态内容时,Velocity模板引擎会扫描整个页面,寻找所有的“#”字符,然后判断这些标记后面的部分是否是VTL语句。如果是,它就会执行相应的模板指令来生成最终的页面。Velocity模板引擎的这种工作...

      Java的模板引擎Velocity初体验.pdf

      Velocity 模板引擎初体验 Velocity 是一种 Java 模板引擎技术,由 Apache 提出,是一种基于 Java 的模板引擎,允许任何人使用简单而强大的模板语言来引用定义在 Java 代码中的对象。Velocity 的主要功能是桥梁 ...

      模板引擎 Velocity 官方最新版下载

      Velocity是一个基于java的模板引擎(template engine)。它允许任何人仅仅简单的使用模板语言(template language)来引用由java代码定义的对象。 当Velocity应用于web开发时,界面设计人员可以和java程序开发人员...

      Velocity文档中文版

      Velocity 是一个基于 Java 的模板引擎(template engine),它允许任何人仅仅简单的使用模板语言(template language)来引用由 Java 代码定义的对象。 Velocity 的能力远不止 web 站点开发这个领域,例如,它可以从...

      Velocity模板引擎 v2.2.0.zip

      在这个"Velocity模板引擎 v2.2.0.zip"压缩包中,包含了一个名为"使用须知.txt"的文件,可能详细介绍了如何安装、配置以及使用这个版本的Velocity。而"132688852448074316"可能是另一个相关文件,但没有具体的文件...

      Velocity模板技术语法详细介绍

      Velocity模板技术语法详细介绍,包括很详细的示例代码 1.变量………………………………………………………………………………1 2.循环………………………………………………………………………………2 3.条件语句...

      Json+NVelocity模板引擎C#入门示例,比较全面

      在IT领域,Json和NVelocity模板引擎是两个重要的技术组件,尤其在C#开发中有着广泛的应用。Json是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。NVelocity则是一个开源的Java模板引擎,...

      模板引擎 Velocity

      ** Velocity 模板引擎** Velocity 是一款开源的 Java 模板引擎,它允许开发者将页面设计与业务逻辑分离,使得 Web 开发更加高效且结构清晰。Velocity 的核心思想是"MVC"(Model-View-Controller)模式,其中 View ...

    Global site tag (gtag.js) - Google Analytics