论优雅编码,多重for循环的DateTime打爆CPU大场面复盘

avatar
@雪球财经

作者:陆洪利

引言

处理过线上问题的同学基本上都会遇到服务器CPU飙升、GC次数过多的问题。
这些问题的最终导致的直观现象就是系统运行缓慢,并且有大量的报警。
本文主要针对服务器CPU飙升这一问题,提供该问题的排查思路,从而定位出问题的代码点,进而提供解决该问题的思路。

问题发现

在计算组合最大回撤算法任务中,每次执行CPU都会有明显的飙升现象。

定位问题

1.查询运行的进程PID,命令:ps -ef | grep java

2.查询进程下所有线程的运行情况,命令:top -Hp PID

3.找到消耗CPU的线程ID,并将ID转换为16进制,命令:printf ‘%x\n’ ID

4.jstack查看线程的信息,命令:jstack PID | grep [线程的16进制] -A 30

图片

5.通过JProfiler工具查看CPU内存的使用情况
jstack命令已经基本能定位到消耗CPU内存的具体方法
为了能够更直观的定位占用内存的堆栈信息,使用JProfiler工具查看方法执行时对象的实例变化

图片

通过实例变化可以直观看到大量DateTime() 对象实例生成

问题解决

通过上述第4步和第5步能定位是V3PlanNavIndicatorCalcUtils.calMaxDrawDownRate() 方法中有大量的DateTime() 对象的生成
DateTime 主要作用对字符串类型的日期(20210818、20210819、... ...)数据排序和比较大小
优化方案是使用字符串的比较功能替换使用DateTime比较

图片

图片

图片

图形对比

1.CPU使用率对比

图片

2.物理机Load对比

图片

3.G1 Young GC对比

图片

总结

以上,展示了一次完整的线上问题的定位解决的过程。
工具用到的有linux命令top、printf、jstack 和 第三方工具JProfiler。
问题主要根源是DateTime()对象大量生成占用内存,同时也导致Young GC频繁垃圾回收。

还有一件事

雪球的工程师团队在招聘啊,Java 工程师,运维开发工程师,测试开发工程师,算法工程师,有意的同学可以查看原文看看具体的职位和要求,就等你了。