`
fantaxy025025
  • 浏览: 1279151 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类

velocity的一些优化记录

 
阅读更多

 

velocity的一些优化记录

背景

前段时间做了个项目,主要优化一个产品页面。整个优化过程中,针对velocity的分析过程占了比较大的比重,这里做一下整理和记录。

 

描述

velocity版本: 

 

Java代码  收藏代码
  1. <dependency>  
  2.     <groupId>org.apache.velocity</groupId>  
  3.     <artifactId>velocity</artifactId>  
  4.     <version>1.6.4</version>  
  5. </dependency>  

优化1: 锁优化

通过velocimacro.library.autoreload=false进行关闭autoreload,因为使用了同步锁,非常影响性能

Java代码  收藏代码
  1. "TP-Processor20" daemon prio=10 tid=0x00002aab4c7cb800 nid=0x3d46 waiting for monitor entry [0x00000000423a3000]  
  2.    java.lang.Thread.State: BLOCKED (on object monitor)  
  3.     at org.apache.velocity.runtime.VelocimacroFactory.getVelocimacro(VelocimacroFactory.java:571)  
  4.     - waiting to lock <0x00002aaad964ca48> (a org.apache.velocity.runtime.VelocimacroFactory)  
  5.     at org.apache.velocity.runtime.RuntimeInstance.getVelocimacro(RuntimeInstance.java:1563)  
  6.     at org.apache.velocity.runtime.directive.RuntimeMacro.render(RuntimeMacro.java:199)  
  7.     at org.apache.velocity.runtime.parser.node.ASTDirective.render(ASTDirective.java:175)  
  8.     at org.apache.velocity.runtime.parser.node.ASTBlock.render(ASTBlock.java:72)  
  9.     at org.apache.velocity.runtime.parser.node.ASTIfStatement.render(ASTIfStatement.java:87)  
  10.     at org.apache.velocity.runtime.parser.node.SimpleNode.render(SimpleNode.java:336)  
  11.     at org.apache.velocity.Template.merge(Template.java:328)  
  12.     at org.apache.velocity.Template.merge(Template.java:235)  

说明: 

1.  velocity针对macros的自动reload,采用了同步排他锁进行控制

2.  在velocity实现中,org.apache.velocity.runtime.VelocimacroFactory.getVelocimacro中,line 569,每次获取一个宏对象,都会进行一个是否需要自动reload的逻辑控制

3.  针对设置了autoReloadLibrary为true时,velocity就会先获取一个同步锁,然后进行相应检查判断是否需要重新载入

 

默认是关闭的,因为公司开发的框架中针对线上和线下velocity参数设置有所不同,在开发环境开启了autoreload,所以导致在测试时发现block现象很严重。

 

优化2: veocity cache策略

velocity针对template查找有一定的cache策略,比如是否启用cache,cache的数量大小。resource.manager.defaultcache.size=89(默认值为89,0代表不限制) 

 

Java代码  收藏代码
  1. TP-Processor12" daemon prio=10 tid=0x00002aab4c868800 nid=0x3d3c waiting on condition [0x0000000042abf000]  
  2.    java.lang.Thread.State: RUNNABLE  
  3.     at org.springframework.core.io.ClassPathResource.getFile(ClassPathResource.java:175)  
  4.     at org.springframework.core.io.AbstractResource.exists(AbstractResource.java:51)  
  5.     at com.alibaba.citrus.service.velocity.impl.AbstractResourceLoader.getLastModified(AbstractResourceLoader.java:72)  
  6.     at org.apache.velocity.runtime.VelocimacroFactory.getVelocimacro(VelocimacroFactory.java:601)  
  7.     - locked <0x00002aaad964ca48> (a org.apache.velocity.runtime.VelocimacroFactory)  
  8.     at org.apache.velocity.runtime.RuntimeInstance.getVelocimacro(RuntimeInstance.java:1563)  
  9.     at org.apache.velocity.runtime.directive.RuntimeMacro.render(RuntimeMacro.java:199)  
  10.     at org.apache.velocity.runtime.parser.node.ASTDirective.render(ASTDirective.java:175)  
  11.     at org.apache.velocity.runtime.parser.node.ASTBlock.render(ASTBlock.java:72)  
  12.     at org.apache.velocity.runtime.parser.node.ASTIfStatement.render(ASTIfStatement.java:87)  
  13.     at org.apache.velocity.runtime.parser.node.SimpleNode.render(SimpleNode.java:336)  
  14.     at org.apache.velocity.Template.merge(Template.java:328)  
  15.     at org.apache.velocity.Template.merge(Template.java:235)  

 

 

1. velocity中使用ResourceManager进行资源查找,在ResourceManagerImpl资源管理查找中,定义了一份resource globalCache

2. 在globalCache.initialize()方法中,会读取定义 resource.manager.defaultcache.size配置,默认值只有89

3. global cache生效,必须要开启对应xxx.resource.loader.cache=true,这样的size调整才有意义,不然velocity个根本不会进行global cache

 

优化3:modificationCheckInterval优化

 

 

  如果开启了优化2,则会对该Resource定期进行是否已经进行了修改的扫描,file.resource.loader.modificationCheckInterval = 2 (单位为秒,如果不需要hot deploy,可以设置更大点)

 

说明:

1.  velocity通过ResourceManagerImpl进行资源加载,在开启优化2后,会针对从cache中返回的resource资源(velocity中模板都认为是一个resource)。

2.  针对resource会进行requiresChecking()判断,主要的依据就是modificationCheckInterval。 0代表永不做检查处理

 

 

优化4: MapGetExecutor优化处理

背景知识

  1. Uberspect : velocity中用于Node render时进行数据解析的一个操作 (introspection/reflection interface)
    • UberspectImpl : Uberspect的默认实现类
    • SecureUberspector(安全调用) , LinkingUberspector(链式支持)
  2. AbstractExecutor :velocity中实现具体$bean交互操作的工具(getMethod , render数据)
    • PropertyExecutor : pojo bean的处理规则,通过getXXX()进行处理
    • BooleanPropertyExecutor : boolean方法处理,通过isXXX()进行处理
    • MapGetExecutor : 如果是Map的子类,通过调用map.get()方法进行处理
    • GetExecutor : 默认调用bean的get()方法进行处理。 我们使用的一些PullTool,比如$form.preTest.defaultInstance,就是调用了$form.get("preTest")
  3. SetExecutor : 和AbstractExecutor相对应,是针对set进行处理.
    • SetPropertyExecutor , MapSetExecutor , PutExecutor 与get处理类似。
问题代码代码  收藏代码
  1. protected void discover (final Class clazz)  
  2.     {  
  3.         Class [] interfaces = clazz.getInterfaces();  
  4.         for (int i = 0 ; i < interfaces.length; i++)  
  5.         {  
  6.             if (interfaces[i].equals(Map.class))  
  7.             {  
  8.                 try  
  9.                 {  
  10.                     if (property != null)  
  11.                     {  
  12.                         setMethod(Map.class.getMethod("get", new Class [] { Object.class }));  
  13.                     }  
  14.                 }  
  15.   
  16.         .......  
  17.             }  
  18.         }  
  19.     }  

 

profile截图:


 

 

代码分析:MapGetExecutor的本意是对一个class如果是Map.class的之类,就委托对应的map.get方法进行处理。但在判断是否是Map之类的过程,通过getInterfaces后进行便利匹配,性能比较差。

优化: 

1. 自定义MapGetExecutor, 直接调用native方法isAssignableFrom进行Map转型判断

 

Custommapgetexecutor代码  收藏代码
  1. if (Map.class.isAssignableFrom(<span style="font-size: 1em; line-height: 1.5;">clazz</span><span style="font-size: 1em; line-height: 1.5;">)) { // 直接调用native方法进行,Map接口判断</span>  
  2.             try {  
  3.                 if (property != null) {  
  4.                     // 通过introspector进行method cache,同时直接查找对象clazz实例的method方法  
  5.                     setMethod(introspector.getMethod(clazz, "get", new Class[] { Object.class }));  
  6.                 }  
  7.            }  

2. 自定义UberspectImpl,引入前面自定义的CustomxMapGetExecutor

 

Customuberspectimpl代码  收藏代码
  1. public VelPropertyGet getPropertyGet(Object obj, String identifier, Info i) throws Exception {  
  2. .......  
  3. if (!executor.isAlive()) {  
  4.             executor = new CustomxMapGetExecutor(log, claz, identifier);  
  5.         }  
  6. .....  
  7. }  

 3. 配置velocity参数,将自定义的CustomUberspectImpl引入到velocity调用

 

Velocity.properties文件代码  收藏代码
  1. runtime.introspector.uberspect=xxxx.velocityx.CustomUberspectImpl  

 

总结一下

最后的优化参数列表

 

Velocity.properties代码  收藏代码
  1. file.resource.loader.cache = true  
  2. file.resource.loader.modificationCheckInterval = 0 #不检查  
  3. resource.manager.defaultcache.size=0 #无限制  
  4.   
  5. velocimacro.library.autoreload=false  
  6.   
  7. runtime.introspector.uberspect = xxxx.velocityx.CustomUberspectImpl  

 

velocity的几个概念

 

  • Resource : 在velocity中每个模板都可以用一个Resource来表示,类似于velocity资源概念。
  • Node : 在velocity中系统引擎对resource解析后的生成的Node对象,可以理解为语法树等概念。主要的基类:SimpleNode
  • Directive : 在velocity系统中定义的一系统指令,比如#foreach ,#if, #macro等。
  • EventHandler & EventCartridge : velocity系统中提供的扩展机制,可以监听在velocity解析,渲染,异常过程中进行自定义的业务处理。比如我们的校长大人的安全框架,在webx3上已经被宝宝内嵌到velocity指令级别,而不是原先定义的宏概念。比如$sql和#escapse('sql')$value#end

说明:

 

 

其他

 

上次在qcon中,taobao的一个分享文章中提到一个char to byte的优化部分。它认为每次的String.tobytes[]都涉及一次StringCoding.encode的转化过程,有点浪费。

一个新的想法: 缓存velocity中的静态文本的String.toBytes()的数据,每次都只做动态数据的toBytes,提升系统性能。

 

这个就做的有点深度了,佩服taobao同学对性能的追求

 

 

分享到:
评论

相关推荐

    velocity Java开发指南中文版

    - **其它细节**: 提供了一些额外的信息,比如性能优化技巧等。 #### 七、Application Attributes (应用程序属性) - **Application Attributes**: 介绍了一些可以在应用程序范围内设置的属性,这些属性可以被多个...

    velocity和freemarker的比较

    标题“velocity和freemarker的比较”涉及到的是两个在Java...提供的文件列表似乎包含了一些日志文件、项目配置文件和源代码库,这可能是项目开发或调试过程中的记录,对于深入理解这两个模板引擎的工作方式有一定帮助。

    velocity的所有jar包

    在Velocity中,它可能被用来记录模板引擎的运行时信息,帮助开发者调试和优化模板。LogKit提供不同级别的日志输出,如DEBUG、INFO、WARN和ERROR,可以根据需要调整日志级别。 4. **velocity-tools-view-1.2.jar**:...

    velocity相关的四个jar包

    例如,开发者可以在Web应用中使用Velocity来生成动态的HTML页面,通过Avalon LogKit进行日志记录,使用Commons Collections优化数据处理,最后通过Velocity Tools View使这一切在Servlet容器中无缝运行。这样的体系...

    apache velocity介绍及资料

    6. **异常处理**:Velocity如何处理模板解析和执行过程中的错误,以及如何配置错误报告和日志记录。 7. **最佳实践**:如何编写高效的、易于维护的Velocity模板,以及如何避免常见的陷阱。 8. **性能优化**:讨论...

    velocity实现静态页面分页

    在Velocity模板中,使用#foreach循环遍历分页模型中的数据列表,展示每条记录。同时,创建两个链接变量,分别表示上一页和下一页的URL。 4. 分页导航: 生成分页导航条,显示页码并链接到相应的URL。你可以使用#...

    velocity实例

    `velocity.log`可能是运行时的日志文件,记录了Velocity引擎处理模板时的详细信息,这对于调试和优化模板逻辑非常有用。 在实际使用中,开发者通常会创建一个或多个数据模型类,然后使用Velocity引擎读取这些模板...

    Apache Velocity - Developer's Guide

    了解如何配置事件处理器对于优化 Velocity 的性能非常重要。 #### 八、Velocity 配置键与值 这一节详细介绍了 Velocity 提供的各种配置选项及其默认值。通过合理设置这些选项,可以显著提高 Velocity 的性能和灵活...

    Velocity初始化过程解析

    Velocity是一个流行的Java模板引擎,常用于构建MVC架构的表示层。它的主要优点在于简洁、高效,无需使用EL(Expression Language)或...理解这个过程有助于优化 Velocity 的性能和日志记录,使其更好地适应项目需求。

    Struts+Velocity整合示例(含源码)

    Interceptor则是拦截器,它可以对请求进行预处理和后处理,比如登录检查、日志记录等。Struts2通过配置文件或注解来定义Action和结果映射,实现灵活的请求处理流程。 **Velocity模板引擎** Velocity强调的是"分离...

    velocity+ssh2+分页+权限

    通常,我们先计算总记录数,然后根据每页显示的条数和当前页码,计算出应获取的数据范围。在Velocity模板中,可以展示分页链接,允许用户切换不同页面。 【权限管理】 权限管理是企业级应用不可或缺的一部分,它...

    Velocity Web应用开发

    - **日志记录的重要性**:合理记录日志有助于排查问题,优化应用性能。 - **日志配置**:配置 Velocity 的日志记录机制,例如使用 Log4j 或 SLF4J。 ##### 5. 部署指南 - **部署注意事项**:在生产环境中部署 ...

    Velocity模板邮件发送例子(Spring框架)(可通用,支持多扩展)

    4. **异常处理**:添加异常处理机制,确保在发送失败时能够记录错误信息,提供重试或通知机制。 5. **扩展性**:设计灵活的接口,允许添加新的邮件服务提供商,或者支持更复杂的邮件配置。 通过以上方法,我们可以...

    maven+druid+mybatis+velocity框架整合

    同时,设置MyBatis的拦截器,使其能够记录SQL日志。Velocity的配置则涉及到视图解析器的设置,确保能够正确找到并解析模板文件。 在实际开发过程中,你还可以利用MyBatis的逆向工程功能,根据数据库表结构自动生成...

    Springmvc+mybatis+velocity+easyui+jquery框架

    MyBatis可以使用简单的XML或注解进行配置和原始映射,将接口和Java的POJOs(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。 【Velocity】 Velocity是Apache软件基金会的一个开源项目,它是一个Java...

    velocity-1.6.1官方开发包

    5. **调试与优化**: 利用 Velocity 提供的工具和日志系统进行问题排查和性能优化。 ** 总结 ** Velocity 1.6.1 官方开发包是一个全面的资源集合,包含了学习和使用 Velocity 所需的所有元素。通过深入研究文档,...

    《Velocity java开发指南》中文版

    Velocity配置键值说明涵盖了如log4j配置、资源加载器设置等,通过修改这些配置,可以优化Velocity的性能和行为。 11. **日志记录配置** 日志系统对于调试和监控应用至关重要,Velocity允许配置不同的日志实现,如...

    velocity分页的例子

    此外,为了优化用户体验,可能还需要考虑分页的懒加载或者无限滚动等高级特性。 总之,Velocity通过其直观的模板语法,使得在Java Web应用中实现分页变得简单易行。开发者只需要关注逻辑处理,模板部分则专注于数据...

Global site tag (gtag.js) - Google Analytics