最近對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