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

HTTL质量分析

阅读更多
抽空写了下对HTTL质量分析的过程,已经加到http://httl.github.com第4章。

性能和设计,理论上也是质量的一部分,但之前已经分析过了,这里不再复述,
请参见:http://httl.github.com第2章和第3章。

先来看看静态代码的分析:

1. 单元测试

单元测试覆盖率: (分析工具EclEmma)



HTTL对所有语法,指令,函数,都有相应模板进行测试,参见:

https://github.com/httl/httl/tree/master/src/test/resources/comment/templates

2. FindBugs检测

已通过FindBugs最新版本(2.0.2)检测,零发现。参见FindBugs能发现的问题:http://findbugs.sourceforge.net/bugDescriptions.html

3. JDepend检测

已通过JDepend检测检测,无环依赖,稳定度与抽象度比正常,参见4.1.3分包设计章节。





我们再来看看运行时的稳定性分析:

4. 稳定性测试

在长时间重复运行所有单元测试后,CPU保持平稳:(分析工具JVisualVM)



内存也保持平稳,以YoungGC为主:



虽然HTTL大量使用字节码生成以提升性能,但因为有全量缓存,Perm区也是稳定的:



因设置的内存只有500M,而常规已占400多M,在OLD区几乎快满情况下,也只发生3次FullGC:(分析工具jstat)





从下面Dump后的数据可以看出,JDK编译占用了171M内存,如果开启-Xlint:unchecked编译参数会更大。
如果你觉得JdkCompiler内存占用过多,也可以通过配置换成Javassist编译。(分析工具jmap + MAT)





5. Profile分析

5.1 CPU分析

测试用例为长时间跑模板渲染过程,因解析后有缓存,所以CPU几乎全耗在渲染过程,
解析过程占比较小,符合预期:(分析工具JProfiler)



因同时测试了Writer和OutputStream两种场景,所以上图中各分一半。

展开其中一个渲染过程,各模板比较均匀,占比都不大,没有出现绝对热点,符合预期:



从上图可以看上,相对而言,xml.httl和include_withfilter.httl较慢,展开如下:



可以看出,主要消耗在xstream的parseXml解析和filter的escapseXml转义上。

XML的解析和处理本身就很耗时,在可接受范围内,并且不是核心组件。

长时间运行后,因样本少,xstream解析数据被缓存,所以时间都集中到了escapseXml的charAt上。



注意,上面的图中,浅红色表示当前方法消耗,深红色表示子函数消耗总和。

即然占比如此大,我们来看下代码:

首先String.charAt只是一个char[]下标取值,已经足够简单,不存在性能问题:

public char charAt(int index) {
    if ((index < 0) || (index >= count)) 
        throw new StringIndexOutOfBoundsException(index);
    return value[index + offset];
}


那再来看看HTTL的escapseXml:

public static String escapeXml(String value) {
    if (value == null || value.length() == 0) {
        return value;
    }
    int len = value.length();
    StringBuilder buf = null;
    for (int i = 0; i < len; i ++) {
        char ch = value.charAt(i);
        switch (ch) {
            case '&':
                if (buf == null) {
                    buf = new StringBuilder(len * 2);
                    if(i > 0) {
                        buf.append(value.substring(0, i));
                    }
                }
                buf.append("&amp;");
                break;
            case '<':
            	if (buf == null) {
                    buf = new StringBuilder(len * 2);
                    if(i > 0) {
                        buf.append(value.substring(0, i));
                    }
                }
                buf.append("&lt;");
                break;
            case '>':
            	if (buf == null) {
                    buf = new StringBuilder(len * 2);
                    if(i > 0) {
                        buf.append(value.substring(0, i));
                    }
                }
                buf.append("&gt;");
                break;
            case '\"':
            	if (buf == null) {
                    buf = new StringBuilder(len * 2);
                    if(i > 0) {
                        buf.append(value.substring(0, i));
                    }
                }
                buf.append("&quot;");
                break;
            case '\'':
            	if (buf == null) {
                    buf = new StringBuilder(len * 2);
                    if(i > 0) {
                        buf.append(value.substring(0, i));
                    }
                }
                buf.append("&apos;");
                break;
            default:
            	if (buf != null) {
                    buf.append(ch);
                }
                break;
        }
    }
    if (buf != null) {
        return buf.toString();
    }
    return value;
}


从代码中可以看出escapseXml已经做了一些优化:

* 在没有发现特殊符前,不创建StringBuilder对象。
* 在发现第一个特殊符时,将将之前的内容,一次性拷到StringBuilder中。
* StringBuilder对象以两倍长度创建,防止扩容带来数据迁移。
* 通过switch每字符,以最短路径分发处理逻辑。

因escapseXml在没有发现特殊符时,只是通过charAt遍历字符串,不会做其它动作,所以长时间运行后,会显得charAt比较热,要过滤至少要遍历一遍,这已经是最低复杂度,所以并不是什么问题。

在压测Apache开源commons-lang中的StringEscapeUtils中的escapeXml后,发现性能甚至不如HTTL的实现。

那也看下commons-lang的StringEscapeUtils源代码:(注释中有说明它慢的原因)

public static String escapeXml(String str) {
    if (str == null) {
        return null;
    }
    return Entities.XML.escape(str);
}

public String escape(String str) {
	// 这里总是创建StringWriter,如果str没有特殊符,这样首先会浪费创建Writer对象的成本。
	// 其次浪费将一个个字符写到writer中,再toString回来的大量性能,而且没有特殊符是大概率事件。
	// HTTL在没有特殊符时是直接返回原始串的,不创建任何对象,不做任何来回拷贝。
	// 另外,StringWriter里面封装的StringBuffer,它的所有方法是带同步锁的,而HTTL采用无锁的StringBuilder。
    StringWriter stringWriter = createStringWriter(str);
    try {
        this.escape(stringWriter, str);
    } catch (IOException e) {
        throw new UnhandledException(e);
    }
    return stringWriter.toString();
}

public void escape(Writer writer, String str) throws IOException {
    int len = str.length();
    for (int i = 0; i < len; i++) {
        char c = str.charAt(i);
        // 这里使用map的hash查找实体的名称,比HTTL的switch慢。
        String entityName = this.entityName(c);
        if (entityName == null) {
            if (c > 0x7F) {
                writer.write("&#");
                writer.write(Integer.toString(c, 10));
                writer.write(';');
            } else {
                writer.write(c);
            }
        } else {
            writer.write('&');
            writer.write(entityName);
            writer.write(';');
        }
    }
}


当然,如果你有更好的实现,欢迎提供,非常感谢。

你可以通过配置切换实现:

value.filters=com.your.YourEscapeXmlFilter


5.2 内存分析

内存中以char[]和String最多,因为模板本身是大量文本处理,符合预期:(分析工具JProfiler)



过滤HTTL自身的类,因Context为会话域模型,每次执行都会创建Context,所以Context类最多,它比较轻量,符合预期:



长时间运行后,Context等实例数保持稳定,并没有爆炸式增长,表示可有效回收,符合预期:

分享到:
评论
6 楼 0372 2017-04-07  
博主好高深呀,我只知道html!
5 楼 gggbdfj 2015-10-26  
梁飞同学,这个httl和装饰器(siteMesh) 能整合吗?
 :shock: 
4 楼 timberwolfes 2015-09-11  
弱弱的问一句:SpringMVC有引入HTTL作为它的ViewResolver吗?就类似于:
org.springframework.web.servlet.view.velocity.VelocityViewResolver
3 楼 610622106 2013-07-15  
 
2 楼 myaniu 2013-06-02  
最近的项目一直在用httl,看中他的简洁和高效。
1 楼 danni505 2013-05-16  
梁飞同学可以整理整理出书了,写的相当专业,亮点在于图多,数据多,说服力很强。

相关推荐

    HTTL模板引擎

    HTTL模板引擎源码 HTTL(Hyper-Text Template Language)是一个高性能的JAVA开源模板引擎,适用于动态HTML页面输出,可替代JSP页面,它的指令和Velocity相似。

    httl-1.0.11 jar包

    比较好的视图层模板引擎

    httl:超文本模板语言和引擎

    超文本模板语言( HTTL )和引擎 文献资料网页:|示例:|用户指南语法:|配置:|开发指南整合:英文|中文设计:英文|中文帮助(常见问题/团队成员):英语|中文 下载https://github.com/httl/httl/tags 或克隆项目...

    基于maven管理的 spring4 0 3+struts2 2 3 16 1+hibernate4 3 4 Final+httl1 0 11 的简单留言本

    自己学习用的,基本上采用都是最新版的程序,jre7编译 不建议直接导入,自己新建maven项目,然后一步步的导入文件,这样有利于学习 1分只是象征,如果一分都没有 ...互相学习,互相进步吧!"&gt;自己学习用的,基本上采用...

    当前流行的模板引擎效率分析(velocity,freeMarker,Smarty4j,httl)

    NULL 博文链接:https://dada-fangfang.iteye.com/blog/1622934

    魔塔游戏开发素材

    这是我自己制作魔塔游戏时找的游戏素材,在这里提供大家下载.

    T4模板使用及CSHTML共5个/第4个

    T4模板使用及CSHTMLT4模板使用及CSHTML

    html颜色库

    可以毫不夸张的说这是所有颜色的代码值库,在这里你可以找到所有你想要的的颜色的代码

    文件的上传与下载过滤操作技术(java jsp )

    这是一套非常有用的文件的上传与下载技术,不会的可以去下载去看一下哦呵呵

    计算机多媒体试题.docx

    考试时间:120分钟 一、单项选择题(每题1分,共50分) MP3代表的含义 A、一种视频格式 B、一种音频格式 C、一种网络协议 D、软件的名称 超文本标记语言是指 A、 WWW B、 HTTL C、 HTML D、 VRML CD-ROM是指 A、...

    多媒体计算机技术试题及答案.doc

    一、单项选择题(每题1分,共50分) 1. MP3代表的含义(B) A、一种视频格式 B、一种音频格式 C、一种网络协议 D... A、 WAV波形文件比MIDI文件的音乐质量高 B、存储同样的音乐文件,WAV波形文件比MIDI文件的存储量大 C

    2018年m301H盒子修复教程

    2018年m301H盒子修复教程,图片显示修复的过程,不需要ttl线刷,只需按照教程即可恢复固件,救砖,黑屏。

    Head First Servlet JSP(清晰中文版).part4

    如果在HTTL中引入Java,JSP则应运而生 2 Web应用体系结构:高层概述 考试要求 什么是容器,容器能带给你什么? 代码里有什么 命名servlet,使用DD将Servlet映射到URL 故事:Bob构建了一个速配网站(MVC) ...

    基于J2EE的员工年假管理系统

    系统框架采用Sping、Struts2和MyBatis,数据库为MySQL,服务器选用tomcat,页面采用httl,并结合JavaScript、jQuery和easyUI插件进行页面效果渲染。系统由登录/退出模块、修改个人密码模块、个人年假信息模块、员工...

    Head First Servlet JSP(清晰中文版).part2

    如果在HTTL中引入Java,JSP则应运而生 2 Web应用体系结构:高层概述 考试要求 什么是容器,容器能带给你什么? 代码里有什么 命名servlet,使用DD将Servlet映射到URL 故事:Bob构建了一个速配网站(MVC) ...

    Head First Servlet JSP(清晰中文版).part3

    如果在HTTL中引入Java,JSP则应运而生 2 Web应用体系结构:高层概述 考试要求 什么是容器,容器能带给你什么? 代码里有什么 命名servlet,使用DD将Servlet映射到URL 故事:Bob构建了一个速配网站(MVC) ...

    Head First Servlet JSP(清晰中文版).part1

    如果在HTTL中引入Java,JSP则应运而生 2 Web应用体系结构:高层概述 考试要求 什么是容器,容器能带给你什么? 代码里有什么 命名servlet,使用DD将Servlet映射到URL 故事:Bob构建了一个速配网站(MVC) ...

    TTL电路

    screen.width-333)this.width=screen.width-333" border=0&gt; 第一代TTL包括SN54/74系列,(其中54系列工作温度为-55℃~+125℃,74系列工作温度为0℃~+75℃) ,低功耗系列简称lttl,高速系列简称HTTL。 第二代TTL...

    小程序豆瓣视频实例

    经测试可以运行,效果不错,适合初学者学习。

    5.19ex1_4.cpp

    5.19ex1_4.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。

Global site tag (gtag.js) - Google Analytics