抛出异常–缓慢而丑陋
這篇文章是關于歷史經驗以及最近應用的性能優化技術的。 幾年前,我在特定的應用程序中發誓,我不得不發現隱藏在真正聰明的工程“技術”之下的無證行為。
它是一個典型的用于發票的單片Java EE應用程序。 最好忘記確切的代碼,但是我記得開發人員已經找到了一種真正聰明的方法來控制業務流程。
流程的一部分通常是無休止的if-then-else混亂,但使事情更加“令人興奮”的是,這些檢查的一些隨機元素被埋入了自定義java.lang.RuntimeException處理機制中。 因此,您可能具有類似于以下內容的代碼:
if (invoice.overdue()) {if (invoice.getCustomer().isKeyCustomer())throw new InvoiceOverdueException(InvoiceOverdueException.KEY_CUSTOMER);elsedoSomething(); } else {if (invoice.getDueAmount() > BIG_AMOUNT)if (invoice.getCustomer().isKeyCustomer())//be silentelsethrow new InvoiceExceededException(invoice.getDueAmount()); }并非像上述那樣簡短易懂的塊,而是在整個應用程序中散布了數千行代碼。
我想你可能同意我的觀點,這是使自己不可或缺的一種好方法。 有人會以一種瘋狂的方式來理解應用程序為什么會如此。
我回想起最近的Plumbr優化任務帶來的經驗。 我想說我們的代碼沒有使用前面案例描述的異常,但是不幸的是,這并非完全正確。 一個特定的方法仍然在代碼的常規流程中構造并拋出RuntimeException 。 由于這個特定模塊的性能異常,我只發現了這個孤獨的反派。
通常,僅在遇到意外問題時才會引發異常。 因此,我們不希望每個線程每秒拋出數千個異常。 但是像我一樣,您可能會發現一種對異常事件使用異常的方法。
我之所以只找到罪魁禍首,是因為這是特定圖形遍歷算法中經常使用的代碼塊,因此從中擠出最后一毫秒至關重要。 立即刪除異常處理使此代碼塊的完成速度提高了100倍以上。
這可能使您想知道–為什么異常處理速度很慢? 最慢的部分與構造異常有關。 或者,更確切地說,是java.lang.Throwable的任何子類。
如果您還記得的話,所有構造函數都會通過調用super()來調用對超類默認構造函數的調用。 如果您未自行指定此調用,則編譯器會友好地將其添加到字節碼本身中。 無論如何,當查看java.lang.Throwable源代碼時,您會看到答案盯著您:
public Throwable() {fillInStackTrace();}public synchronized Throwable fillInStackTrace() {if (stackTrace != null ||backtrace != null /* Out of protocol state */ ) {fillInStackTrace(0);stackTrace = UNASSIGNED_STACK;}return this;}private native Throwable fillInStackTrace(int dummy);因此,每次創建新的Throwable()時,最終都會通過本機調用填充整個堆棧跟蹤。 如果您不認為這很慢,請執行以下jmh微基準測試,以驗證創建異常的費用比構造常規對象的費用高數百倍:
@BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.NANOSECONDS) public class NewExceptionTest {@GenerateMicroBenchmarkpublic Object baseline() {return new Object();}@GenerateMicroBenchmarkpublic Object exceptional() {return new RuntimeException();} }Benchmark Mode Thr Cnt Sec Mean Mean error Units j.NewExceptionTest.baseline avgt 1 5 5 3.275 0.029 nsec/op j.NewExceptionTest.exceptional avgt 1 5 5 1329.266 8.675 nsec/op 總而言之,在特殊情況下,名稱應表示例外。 如果您開始濫用該概念,那么您要么使代碼不可讀,要么開始遭受性能問題的困擾。 至少,我保證您會從中獲得大量的負面因果報應。
翻譯自: https://www.javacodegeeks.com/2013/08/throwing-exceptions-slow-and-ugly.html
總結
以上是生活随笔為你收集整理的抛出异常–缓慢而丑陋的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 国寿周周盈收益怎么不更新?
- 下一篇: 安全地创建和存储密码