在解决了编译问题后, 就能够实时每一个方法的调用耗时. 以后面临新的问题:java
简单的看这两个问题, 1是如何描述一个方法,
那么首先想到的就是thread.getStackTrace().bash
然而实际直接获取thread.getStackTrace()是有问题的:markdown
既然thread.getStackTrace()不可取, 那必须须要考虑其余办法了.
数据结构
首先分析咱们的目的:优化
一个方法, 可能被父方法调用, 也可能调用多个子方法. 有上下父子关系, 也要先后兄弟关系.
那么将每一个方法看作一个节点, 有一下特色this
好比以下代码:spa
void method1(){ method2(); method3(); method4(); } void method2(){ method5(); } void method3(){ method6(); method7(); } void method4(){ } 复制代码
用图形表达后, 应该相似这个样子:code
因此咱们能够模拟一套树形结构来记录方法堆(就不能说是栈了:)).orm
数据结构确认后, 实现就容易了. 使用任意的List, 就能够实现:内存
class MethodNode{ //父方法节点 MethodNode parent; //子方法节点 List<MethodNode> children; //当前方法名 String methodName; } 复制代码
所以如上代码中的method3(), 用数结构记录的话, 大体是下面这个样子:
(只是个大概, 由于mermaid绘图有些诡异, 因此有不许确的地方)
确认了数据结构, 接下来考虑如何关联各个方法节点.
目前, 已经在每一个方法的起始和结束插入了代码用来计算方法耗时,
那么也能够扩展这些被插入代码, 将各个方法关联起来.
以下伪代码所示. 任什么时候间, 只要root不为空, 均可以经过root获取当前已经保存的全部方法调用堆栈.
//当前正在运行的方法 static MethodNode currNode; //根节点方法 static MethodNode root; void onMethodStart(MethodNode methodNode){ //方法开始, 记录时间 methodNode.startTime = System.currentTimeMillis(); if(currNode != null){ //设置父方法 methodNode.parent = currNode; //父方法中添加子方法 currNode.children.add(methodNode); //更新当前方法. currNode = methodNode; } if(root==null){ //设置根方法 root = this; currNode = this; } } void onMethodEnd(MethodNode methodNode){ //方法结束, 记录时间 methodNode.endTime = System.currentTimeMillis(); //更新当前方法currNode为父方法 currNode = methodNode.parent; } 复制代码
以上初步实现了方法监控功能的记录. 可是由于实时存储了方法的调用信息, 因此内存激增. 致使内存问题. 如何优化, 待后续...