簡體   English   中英

訪問堆棧跟蹤具有良好的性能?

[英]Access stacktraces with good performance?

我們最近應用了幾乎所有應用程序模塊/組件(大約50個項目)使用的緩存解決方案。 為了更好地了解在不同的系統“位置”上執行哪些緩存操作,我們為當前執行的緩存操作添加了日志記錄,包括堆棧跟蹤,以准確了解觸發緩存操作的內容。

我們當前的方法如下所示:我們從新的Throwable()中獲取堆棧跟蹤,過濾不相關的行並記錄剩余的堆棧跟蹤。 盡管如此,創建一個新的異常以便記錄是不便宜的。 由於我們不直接使用緩存,而是通過休眠,因此找不到哪個調用者在沒有訪問堆棧跟蹤的情況下觸發了操作就不那么容易了。

我的問題是:是否有一個更高效的解決方案來訪問當前的堆棧跟蹤然后Throwable()。getStackTrace或Thread.currentThread()。getStackTrace()?

實際上獲取異常堆棧跟蹤並不是那么慢:

  • 收集回溯只花費10%的時間 - 這是在Throwable()構造函數中完成的;
  • 其他90%的時間用於回溯從內部格式轉換為可讀的StackTraceElement[]數組 - 這是在getStackTrace()

這意味着,如果您不需要同步處理堆棧跟蹤,則只需調用new Exception() (這或多或少是快速操作),然后在另一個線程中稍后或異步調用e.getStackTrace()

此外,有時(如在您的情況下)不需要完整的堆棧跟蹤。 您可以跳過一些堆棧幀並僅解碼您感興趣的那些。神奇的sun.misc.SharedSectets類將有所幫助。

例如,只獲得第2幀到第5幀,請使用

Exception e = new Exception();
int depth = Math.min(5, SharedSecrets.getJavaLangAccess().getStackTraceDepth(e));

for (int frame = 2; frame < depth; frame++) {
    StackTraceElement elem = SharedSecrets.getJavaLangAccess().getStackTraceElement(e, frame);
    System.out.println(elem);
}

Thread.currentThread().getStackTrace()與@apangin指出的基本相同,但如果它避免創建Throwable,它將來會更快。

但是,您可能會發現子采樣將為您提供所需的改進。 而不是記錄每次訪問,記錄每第N次訪問。 如果你記錄每10次訪問,你可以減少高達90%的開銷,如果你有大量的訪問,它將幾乎一樣准確。

另一種選擇是使用像YourKit這樣的分析器,它可以更有效地完成這項工作。 這可以顯示方法及其堆棧跟蹤的不同調用方數(通常每10個記錄一次)

您還可以做的是實現一個java代理 這將正確地檢測您想要跟蹤的代碼片段。

在這里,您將找到如何開始

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM