通过线程信息分析CPU
1.查看线程信息
step1: 先查看哪个线程占比cpu最高
分析:
可与看出 SceneWorker占比最高,但是是哪个类中哪个方法则不是太清楚。
我们还需要去分析代码:
step2.分析代码
1.AbstractSceneManager的 this.sceneWorkers = new SceneExecutor("SceneWorker", sceneWorkerNum); 创建,接下来我们这个线程看下在哪里调用
2.AbstractSceneManager的 execute调用 // 里面发现了sleep方法,其实也就是服务器的帧率了. < 100ms不打印,超过则打印
这个execute是在run方法体
在Application的:
bigWorldSceneManager = new BigWorldSceneManager(1, 8);
bigWorldSceneManager.start();
3.看下execute做了什么事:
// 处理场景tick更新
sceneWorkers.forEach(scenes.values(), scene -> scene.tick(now), false);
分析:
这个scene是BigWorldScene。 负责这个沙盘的更新。也就是: AbstraceScene的tick方法,我们进来查看
4.[arthas@18936]$ trace com.elex.icefire.scene.AbstractScene tick -n 10
Press Q or Ctrl+C to abort.
Affect(class count: 2 , method count: 2) cost in 255 ms, listenerId: 6
`---ts=2024-01-24 10:48:25;thread_name=SceneWorker-thread-1;id=112;is_daemon=false;priority=5;TCCL=jdk.internal.loader.ClassLoaders$AppClassLoader@7aec35a
`---[29.621905ms] com.elex.icefire.scene.BigWorldScene:tick()
`---[99.50% 29.472456ms ] com.elex.icefire.scene.AbstractScene:tick() #82
`---[99.88% 29.437892ms ] com.elex.icefire.scene.AbstractScene:tick()
+---[0.19% 0.055634ms ] com.elex.icefire.scene.event.SceneEventManager:onTiming() #336
+---[0.01% 0.003456ms ] com.elex.icefire.scene.event.SceneEventManager:onTiming() #338
+---[0.06% 0.017392ms ] com.elex.icefire.scene.object.SceneObjectContainer:getAll() #340
`---[99.11% min=0.004368ms,max=13.884755ms,total=29.177286ms,count=5] com.elex.icefire.scene.ticker.ISceneObjectTicker:updateObjects() #366
因此最终使用trace去定位到底哪行代码占用cpu最长
通过火焰图分析CPU
分析:
很清晰看出来:是心跳占用时间长,我们可以结合trace进一步分析到底哪个类中哪个方法占用时间长。
通过火焰图分析内存
1.开始内存火焰图采样
profiler start -e alloc
2.输出火焰图采样html
profiler stop --format html
3.输出下profiler状态
profiler status
4.打开火焰图
分析
横向:表示执行时间占比。
竖向:代表栈调用深度(这个我不太理解)
看下蓝色的就知道哪个对象最多,目前看出来是: HashMap啥的。