在解決了編譯問題後, 就能夠實時每一個方法的調用耗時. 以後面臨新的問題: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; } 複製代碼
以上初步實現了方法監控功能的記錄. 可是由於實時存儲了方法的調用信息, 因此內存激增. 致使內存問題. 如何優化, 待後續...