性能是 java 平臺屢屢受到指責的一個方面。然而,Java 平臺的巨大成功也使得對性能問題作一番嚴厲的調查研究頗有必要。在這個新專欄中,無畏的優化大師 Jack Shirazi 和 Kirk Pepperdine,分別是 JavaPerformanceTuning.com 的董事和 CTO,他們在整個 Internet 上推行性能大討論,展開他們所碰到的問題并加以澄清。本月,他們來到 JavaRanch,討論有關編譯速度、異常以及堆長度調優等方面的話題。
上個月,我們在 JavaRanch 的 Big Moose Saloon 板塊上花了大量的時間,以便查看 JavaRanch 的生手會提出什么樣的性能方面的疑問。后來發現,大部分問題都是關于 J2SE 和開發過程的——提出的問題主要是關于 Java 語言、核心類以及如何改進他們的開發過程。
編譯速度
您是否曾發現您的編譯階段很慢?是不是 javac 所花的時間太長?那么試試 Jikes 編譯器吧,在創建 .class 文件時,它會加入額外的“動力”。這就是新興的 Jikes,它擁有完整的 Java 源支持。(可能會引起 VerifyError,不支持所有的 javac 選項,字節碼可能不像所說的那么好,而且性能也可能受到影響。因此,在使用之前,請務必閱讀使用手冊。)
所以說,在 JavaRanch 上對 Jikes 的討論不像我們自制的廣告那么直接,但是有的讀者也明確指出,Jikes Java 編譯器是設計用來加快編譯速度的。知道這一點很有用,尤其是對于那些需要編譯很多文件的項目更是如此。不過要清楚,雖然 Jikes 有助于加快開發進程,但是對于最后的編譯,最好還是使用與在生產中將要使用的 JVM 一起提供的那個編譯器。不同的 JVM 版本會有不同的情況,所以當使用來自不同 JVM 的編譯器時就可能引發問題。
異常開銷很大
是的,異常開銷很大。那么,這是不是就意味著您不該使用異常?當然不是。但是,何時應該使用異常,何時又不應該使用異常呢?不幸的是,答案不是一下子就說得清的。
我們要說的是,您不必放棄已經學到的好的 try-catch 編程習慣,但是使用異常時可能會碰到麻煩,創建異常就是一個例子。當創建一個異常時,需要收集一個棧跟蹤(stack track),這個棧跟蹤用于描述異常是在何處創建的。還記得當代碼中拋出一個意料之外的異常時,您所看到的輸出來的棧跟蹤嗎?像下面這個:
Exception in thread "main" my.corp.DidntEXPectThisException
at T.noExceptionsHere(T.java:13)
at T.main(T.java:7)
構建這些棧跟蹤時需要為運行時棧做一份快照,正是這一部分開銷很大。運行時棧不是為有效的異常創建而設計的,而是設計用來讓運行時盡可能快地運行。入棧,出棧,入棧,出棧。讓這樣的工作順利完成,而沒有任何不必要的延遲。但是,當需要創建一個 Exception 時,JVM 不得不說:“先別動,我想就您現在的樣子存一份快照,所以暫時停止入棧和出棧操作,笑著等我拍完快照吧。”棧跟蹤不只包含運行時棧中的一兩個元素,而是包含這個棧中的每一個元素,從棧頂到棧底,還有行號和一切應有的東西。假如在一個深度為20的棧中創建了異常,那么就別指望只記錄頂部的幾個棧元素了——您得完完整整地記錄下所有20個元素。從 main 或 Thread.run (在棧底)到棧頂,記錄整個棧。
因此,創建異常這一部分開銷很大。從技術上講,棧跟蹤快照是在本地方法 Throwable.fillInStackTrace() 中發生的,這個方法又是從 Throwable contrUCtor 那里調用的。但是這并沒有什么影響——假如您創建一個 Exception,就得付出代價。好在捕捉異常開銷不大,因此可以使用 try-catch 將核心內容包起來。您也可以在方法定義中定義 throws 子句,這樣對性能不會造成什么損失,例如:
public Blah myMethod(Foo x) throws SomeBarException {
....
從技術上講,您甚至可以隨意地拋出異常,而不用花費很大的代價。招致性能損失的并不是 throw 操作——盡管在沒有預先創建異常的情況下就拋出異常是有點不平常。真正要花代價的是創建異常。
try {
doThings();
if (true)
throw new SomeException(); // cos my PRogram runs too fast
}
catch(SomeException e) {
doMoreThings();
}
幸運的是,好的編程習慣已教會我們,不應該不管三七二十一就拋出異常。異常是為異常的情況而設計的,使用時也應該牢記這一原則。但是,萬一您不想遵從好的編程習慣,Java 語言就會讓您知道,那樣做可以讓您的程序運行得更快,從而鼓勵您去那樣做。
最大堆長度
在我們訪問過的所有討論組中,有關 JVM 堆的問題不斷冒出。在 JavaRanch 上有一次討論就是以“最大堆長度設置應該是怎樣的?”這一基本問題開始的。在深入研究之前,讓我們先復習一下 Java 運行時中內存治理的基礎知識。
新聞熱點
疑難解答