最近对aocache 进行了重要升级,最新版本0.6.0增加了几项新功能:性能分析日志,AOCache性能分析工具,切入点自定义配置,全局配置,本文详细说明这几项目新功能的作用和使用方式。
一、性能分析日志
需求背景
对于哪些方法适合使用aocache注解提高性能,开始我是凭经验和直觉来判断的。
但是对于下面这个方法,凭直觉你觉得用方法缓存能提高性能么?
public String next(String expression) {
if (expression == null || expression.length() == 0) {
return null;
}
boolean indexed = false;
boolean mapped = false;
for (int i = 0; i < expression.length(); i++) {
char c = expression.charAt(i);
if (indexed) {
if (c == ']') {
return expression.substring(0, i + 1);
}
} else if (mapped) {
if (c == ')') {
return expression.substring(0, i + 1);
}
} else {
if (c == '.') {
return expression.substring(0, i);
} else if (c == '(') {
mapped = true;
} else if (c == '[') {
indexed = true;
}
}
}
return expression;
}
这是一个太简单的循环字符比较。不涉及任何复杂的计算。
我觉得它的计算量不大,凭经验觉得它的计算量不大,而且执行结果与字符串长度有关,但这个方法的调用频率非常高。
我意识到,要真正有效得应用aocache提供的方法计算结果缓存功能以提高系统整体执行效率,开发人员需要一种定量化的分析机制,为方法计算结果缓存功能提供更准确的执行效能评估。以帮助开发人员判断是否启用方法计算结果缓存功能。
要提供定量化的分析,首先aocache需要提供性能分析日志功能,即aocache执行切入点(JoinPoint)方法时能够准确记录每次切入点调用执行时间并持久化保存(csv)。
有了这些原始的记录,才能谈后续分析,借助AI,应该能很方便的解决问题。
设计目标
- 建立定量化监控机制,记录每个被缓存方法的计算耗时和缓存调用耗时
- 生成结构化数据文件(CSV)供离线分析
- 减少性能监控对系统本身的影响(异步持久化机制)
csv
记录的字段JoinPoint
[String]方法签名,字符串中有,
号,所以需要前后用双引号包括。ArgsHash
[Integer]方法调用参数的hash code,不需要保存完整参数,否则数据量太大Count
[Long]方法调用的计数器,用于区分是计算执行
(=1)用还是缓存命中
(>1),参见 InvokeKey.aroundCounter字段Cost
[Long]方法调用执行时间(纳秒)
使用方式
性能分析日志默认是关闭的,你可以命令行参数:在启动 JVM 时,添加 -Daocache.profiler.enableLog=true
参数来开启性能日志记录。例如:
java -Daocache.profiler.enableLog=true -jar your-application.jar
二、AOCache性能分析工具
演进历程
当我拿到这样的CSV日志文件后,真是天书啊。尝试用AI或EXCEL进行分析,发现很麻烦。
于是我决定将基于csv文件性能的分析工具化。设计一个python脚本来执行对原始csv文件的分析
-
计算每个JoinPoint的计算执行平均时间(
RA
)和缓存命中平均时间(CA
),时间单位转为毫秒,计算执行次数(RC),缓存命中次数(CC) -
计算每个JoinPoint的总执行时间(
JT
)和JoinPoint总执行次数(JC
) -
计算每个JoinPoint 所有调用中 缓存命中的比例(
CR
),即CR=CC/(RC + CC)
-
计算每个JoinPoint 缓存命中的效率(
CEM
),即CEM=RA/CA
-
计算每个JoinPoint出缓存命中调用与计算执行所用开销减少比例,即综合性能提升百分比(PR),公式
PR=JT/(RA x JC) x 100
,RA x JC
可以理解为假设所有执行都是在没有缓存命中的执行总时间,JT与它的比值就可以理解使用缓存功能后执行时间减少的。
核心指标
- CEM(缓存效率倍数):量化缓存带来的效率提升
- LEVEL(优化等级):★级指导配置决策
- CR(缓存命中率):验证缓存配置合理性
使用示例
# 分析当天日志,输出为html
python aopanalyzer.py
# 分析当天日志,输出为xlsx
python aopanalyzer.py --output xlsx
# 分析指定日期日志(20240315)
python aopanalyzer.py 20240315 --output report.xlsx
# 分析指定文件
python aopanalyzer.py input.csv --output analysis.html
生成报告(HTML)示例:
三、切入点自定义配置
核心痛点
aocache通过注解方式定义方法启用计算缓存,对于每一个切入点而言,在编译期就已经定义了缓存的配置(weakKeys,maximumSize,expireAfterAccess等等)。
但实际应用场景中,通过AOCache 性能分析结果,可能会发现有些配置对切入点的综合性能提升并不理想,需要调整,这种情况下,如果切入点并不在当前项目,想要根据应用场景修改切点,就会很麻烦。
所以需要一种切入点(JoinPoint)自定义配置机制,可以允许通过外部以切入点配置文件的形式对切入点的配置进行调整。
配置文件示例
如下以**${JoinPoint}=配置描述字符串**的形式对切入点进行调整:
# 关闭切入点缓存能力
execution(public static java.util.Date com.gitee.l0km.aocache.example.ctw.DateSupport.parseDateString(java.lang.String, java.lang.Class))=false
# 定义切入点缓存配置
call(com.gitee.l0km.aocache.example.ctw.AocacheCtwTest.TestUser())={weakKeys=true,maximumSize:100}
启用配置
需要设置usingLoadedJoinPoints=true
启用自定义切入点配置功能:
1. 修改默认配置文件
在${user.home}/.aocache/aoconfig.properties
中添加:
usingLoadedJoinPoints=true
2. 系统属性配置
启动JVM时添加参数:
java -Daocache.usingLoadedJoinPoints=true -jar your-app.jar
切入点配置文件加载位置与优先级
- 类路径配置:
META-INF/aocache.joinpoints
文件(支持多JAR包聚合) - 用户目录配置:
${java.home}/.aocache/aocache.joinpoints
文件 - 环境变量配置:
AOCACHE_JOINPOINTS
环境变量指定的文件
四、全局配置
核心价值
允许应用程序从外部配置文件来控制这些全局配置参数。
配置文件示例
${user.home}/.aocache/aoconfig.properties:
# AoCache Configuration
# 基础配置
# debugOutput: 是否启用调试输出(默认:false)
#logger.debugOutput=false
# debugOutputDetail: 是否输出详细调试信息(默认:false)
#logger.debugOutputDetail=false
# override: 是否启用注解定义的日志配置覆盖全局配置(默认:false)
#logger.override=false
# usingLoadedJoinPoints: 是否使用加载的切入点配置(默认:false)
#usingLoadedJoinPoints=false
# outputAroundCost: 是否输出环绕方法耗时(默认:false)
#logger.outputAroundCost=false
# 性能分析配置
# profiler.enableLog: 是否启用性能分析(默认:false)
#profiler.enableLog=false
# profiler.logFolder: 缓存性能分析器的日志文件夹路径,默认${user.home}/.aocache/profiler
#profiler.logFolder=
# profiler.flushInterval: 性能分析日志写入间隔时间(毫秒),默认5000
#profiler.flushInterval=5000
# profiler.cleanLogFile: 是否在启动时清理旧的性能分析日志文件(默认:false)
#profiler.cleanLogFile=false
总结:打造性能优化闭环
通过监控采集 → 分析定位 → 动态调整 → 固化配置
的完整链路,aocache实现了缓存优化的科学决策。
详细说明参见码云仓库:aocache