背景

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

描述

velocity版本:

  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,因为使用了同步锁,非常影响性能

  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代表不限制)

  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. }

profile截图:

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

优化:

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

  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

  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调用

  1. runtime.introspector.uberspect=xxxx.velocityx.CustomUberspectImpl

总结一下

最后的优化参数列表

  1. file.resource.loader.cache = true
  2. file.resource.loader.modificationCheckInterval = 0 #不检查
  3. resource.manager.defaultcache.size=0 #无限制
  4. velocimacro.library.autoreload=false
  5. 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的一些优化记录的更多相关文章

  1. VS2010/2012配置优化记录笔记

    VS2010/2012配置优化记录笔记 在某些情况下VS2010/2012运行真的实在是太卡了,有什么办法可以提高速度吗?下面介绍几个优化策略,感兴趣的朋友可以参考下,希望可以帮助到你   有的时候V ...

  2. React性能优化记录(不定期更新)

    React性能优化记录(不定期更新) 1. 使用PureComponent代替Component 在新建组件的时候需要继承Component会用到以下代码 import React,{Componen ...

  3. Loogn.OrmLite映射优化记录

    大家对ORM效率的争议多半在映射性能方面.自己的ORMLite也是如此,经过前段时间的折腾,已经找不出一个简单的方法再提升一下这部分的方法了.在此把优化涉及的几点记录一下. 注:用于性能测试的Code ...

  4. 我的搜索优化记录(一):中文分词优化IK Analyzer

    搜索绝对不仅仅是搭起框架,跑出结果就完成的工作,之后分词.排序等等的优化才是重头戏. 先交代下背景:这个搜索是我一个人负责搭建并优化的项目,主要索引对象为歌曲.歌手MV等等. 使用技术:Lucene. ...

  5. ElasticSearch CPU和内存占用高的优化记录

    公司最近使用ElasticSearch作为数据报表汇总引擎.上线三个月累计数据800万,但是今天突然大面积出现查询超时,上服务器查看服务运行情况,发现cpu使用率高达300% mem 使用率也到了90 ...

  6. mysql参数优化记录

    服务器参数16G内存,4核CPUvim /etc/my.cnf 原: back_log=170 max_connections=600 max_user_connections=0 thread_co ...

  7. Unity Ulua1.03优化记录

    现在项目的框架是在2015年设计的,那时候Ulua还处于1.03版本,现在回头再看,Ulua已经迭代到1.25版本,中间引入带有wraper的cstolua,而后转向现有的toLua#版本. 随着版本 ...

  8. 【mysql】索引优化记录

    基础知识 Innodb存储引擎 支持行锁 支持事务: Myisam存储引擎 只支持表锁: 不支持事务: 常见索引列表 独立的列 前缀索引(索引选择性) 多列索引(并不是多个单列索引,索引顺序很重要) ...

  9. Linux内核参数优化记录

    //fs.file-max 最大打开文件数 //fs.nr_open=20480000 单个进程允许打开的文件句柄上限 //信号量及共享内存,可以使用ipcs -l来获取 //kernel.sem 信 ...

随机推荐

  1. Asp.Net MVC Razor视图引擎与My97DatePicker插件的结合

    using System; using System.Collections.Generic; using System.Runtime.CompilerServices; using System. ...

  2. 单元测试+内存、SD卡、SP读写+XmlPullParser

    测试: 测试的相关概念 1.根据是否知道源代码分类: 黑盒测试: a - b - c 边值测试 测试逻辑业务 白盒测试: 根据源代码写测试方法 或者 测试用例; 2.根据测试的粒度分类: 方法测试:写 ...

  3. 8-15 Shuffle uva12174

    题意: 你正在使用的音乐播放器有一个所谓的乱序功能,即随机打乱歌曲的播放顺序.假设一共有s首歌,则一开始会给这s首歌随机排序,全部播放完毕后再重新随机排序.继续播放,依此类推.注意,当s首歌播放完毕之 ...

  4. Ionic Js二:背景层

    我们经常需要在 UI 上,例如在弹出框.加载框.其他弹出层中显示或隐藏背景层. 在组件中可以使用\(ionicBackdrop.retain()来显示背景层,使用\)ionicBackdrop.rel ...

  5. CSUOJ 1341 String and Arrays

    Description 有一个N*N的字符矩阵,从上到下依次记为第1行,第2行,--,第N行,从左至右依次记为第1列,第2列,--,第N列.    对于这个矩阵会进行一系列操作,但这些操作只有两类:  ...

  6. GPS数据包格式及数据包解析

    GPS数据包解析 GPS数据包解析 目的 GPS数据类型及格式 数据格式 数据解释 解析代码 结构体定义 GPRMC解析函数 GPGGA解析函数 测试样例输出 gps数据包格式 gps数据解析 车联网 ...

  7. phantomjs-prebuilt@2.1.16 install: `node install.js`

    今天运行vue项目安装项目依赖(npm install)的时候,报这个错误: 解决办法: npm -g install phantomjs-prebuilt@2.1.16 --ignore-scrip ...

  8. java设计模式(三)模板模式

    抽象类中公开定义了执行它的方法的方式,子类可以按需求重写方法实现,但调用将以抽象类中定义的方式进行,典型应用如银行办理业务流程.冲泡饮料流程.下面给出简单例子,用沸水冲泡饮料,分为四步:将水煮沸.泡制 ...

  9. Java Maven:spring boot + Mybatis连接MySQL,通用mapper的增删改查,映射实现多表查询

    1. MySQL自带库test添加表user.role 角色表role 用户表user 2. 添加依赖,配置属性 相关依赖:百度即可,此处略 application.properties spring ...

  10. setTimeout 第一个参数类型

    读别人代码的时候看到这么一段,很不理解,然后就搜了一下百度 setTimeout / setInterval 第一个参数可以有三种类型: 字符串   .  methods  .  匿名函数 1.字符串 ...