您的位置:首頁 >  新聞中心 > 行業(yè)動(dòng)態(tài)
  行業(yè)動(dòng)態(tài)
 

11 個(gè)簡單的 Java 性能調(diào)優(yōu)技巧

來源:原創(chuàng)    時(shí)間:2017-11-09    瀏覽:0 次

大多數(shù)開發(fā)人員天經(jīng)地義地以為功用優(yōu)化很雜亂,需求許多的經(jīng)歷和常識(shí)。好吧,不能說這是徹底過錯(cuò)的。優(yōu)化運(yùn)用程序以取得最佳功用不是一件簡略的作業(yè)??墒牵@并不意味著如果你不具備這些常識(shí),就不能做任何作業(yè)。這里有11個(gè)易于遵從的主張和最佳實(shí)踐能夠協(xié)助你創(chuàng)立一個(gè)功用杰出的運(yùn)用程序。
java-logo-6
大部分主張是針對(duì)Java的。但也有若干主張是與言語無關(guān)的,能夠運(yùn)用于一切運(yùn)用程序和編程言語。在評(píng)論專門針對(duì)Java的功用調(diào)優(yōu)技巧之前,讓我們先來看看通用技巧。
1.在你知道必要之前不要優(yōu)化
這可能是最重要的功用調(diào)整技巧之一。你應(yīng)該遵從常見的最佳實(shí)踐做法并測驗(yàn)高效地完成用例??墒?,這并不意味著在你證明必要之前,你應(yīng)該替換任何規(guī)范庫或構(gòu)建雜亂的優(yōu)化。
在大多數(shù)狀況下,過早優(yōu)化不光會(huì)占用許多時(shí)刻,并且會(huì)使代碼變得難以閱覽和保護(hù)。更糟糕的是,這些優(yōu)化一般不會(huì)帶來任何優(yōu)點(diǎn),因?yàn)槟慊ㄙM(fèi)許多時(shí)刻來優(yōu)化的是運(yùn)用程序的非要害部分。
那么,你怎么證明你需求優(yōu)化一些東西呢?
首要,你需求界說運(yùn)用程序代碼的速度得多快,例如,為一切API調(diào)用指定最大呼應(yīng)時(shí)刻,或許指定在特定時(shí)刻規(guī)模內(nèi)要導(dǎo)入的記載數(shù)量。在完結(jié)這些之后,你就能夠丈量運(yùn)用程序的哪些部分太慢需求改進(jìn)。然后,接著看第二個(gè)技巧。

2.運(yùn)用剖析器查找真實(shí)的瓶頸
在你遵從第一個(gè)主張并斷定了運(yùn)用程序的某些部分需求改進(jìn)后,那么從哪里開端呢?
你能夠用兩種辦法來處理問題:
查看你的代碼,并從看起來可疑或許你覺得可能會(huì)發(fā)作問題的部分開端。
或許運(yùn)用剖析器并獲取有關(guān)代碼每個(gè)部分的行為和功用的詳細(xì)信息。
期望不需求我解說為什么應(yīng)該一直遵從第二種辦法的原因。
很明顯,根據(jù)剖析器的辦法能夠讓你更好地了解代碼的功用影響,并使你能夠?qū)P挠谧钜Φ牟糠?。如果你曾運(yùn)用過剖析器,那么你必定記住從前你是多么驚奇于一下就找到了代碼的哪些部分發(fā)作了功用問題。老實(shí)說,我第一次的猜想不止一次地導(dǎo)致我走錯(cuò)了方向。
3.為整個(gè)運(yùn)用程序創(chuàng)立功用測驗(yàn)套件
這是另一個(gè)通用技巧,能夠協(xié)助你防止在將功用改進(jìn)布置到生產(chǎn)后常常會(huì)發(fā)作的許多意外問題。你應(yīng)該總是界說一個(gè)測驗(yàn)整個(gè)運(yùn)用程序的功用測驗(yàn)套件,并在功用改進(jìn)之前和之后運(yùn)轉(zhuǎn)它。
這些額定的測驗(yàn)運(yùn)轉(zhuǎn)將協(xié)助你辨認(rèn)更改的功用和功用副作用,并保證不會(huì)導(dǎo)致弊大于利的更新。如果你作業(yè)于被運(yùn)用程序若干不同部分運(yùn)用的組件,如數(shù)據(jù)庫或緩存,那么這一點(diǎn)就特別重要。
4.首要處理最大的瓶頸
在創(chuàng)立測驗(yàn)套件并運(yùn)用剖析器剖析運(yùn)用程序之后,你能夠列出一系列需求處理以進(jìn)步功用的問題。這很好,但它仍然不能答復(fù)你應(yīng)該從哪里開端的問題。你能夠?qū)P挠谒傩в?jì)劃,或從最重要的問題開端。
速效計(jì)劃一開端可能會(huì)很有吸引力,因?yàn)槟隳軌蚝芸祜@現(xiàn)第一個(gè)作用。但有時(shí),可能需求你壓服其他團(tuán)隊(duì)成員或辦理層以為功用剖析是值得的——因?yàn)闀簳r(shí)看不到作用。
但總的來說,我主張首要處理最重要的功用問題。這將為你供給最大的功用改進(jìn),并且可能再也不需求去處理其間一些為了滿意功用需求的問題。
常見的功用調(diào)整技巧到此結(jié)束。下面讓我們細(xì)心看看一些特定于Java的技巧。
5.運(yùn)用StringBuilder以編程辦法銜接String
有許多不同的選項(xiàng)來銜接Java中的String。例如,你能夠運(yùn)用簡略的+或+ =,以及StringBuffer或StringBuilder。
那么,你應(yīng)該挑選哪種辦法?
答案取決于銜接String的代碼。如果你是以編程辦法增加新內(nèi)容到String中,例如在for循環(huán)中,那么你應(yīng)該運(yùn)用StringBuilder。它很簡略運(yùn)用,并供給比StringBuffer更好的功用。但請記住,與StringBuffer比較,StringBuilder不是線程安全的,可能不適合一切用例。
你只需求實(shí)例化一個(gè)新的StringBuilder并調(diào)用append辦法來向String中增加一個(gè)新的部分。在你增加了一切的部分之后,你就能夠調(diào)用toString()辦法來檢索銜接的String。
下面的代碼片段顯現(xiàn)了一個(gè)簡略的比如。在每次迭代期間,這個(gè)循環(huán)將i轉(zhuǎn)換為一個(gè)String,并將它與一個(gè)空格一同增加到StringBuilder sb中。所以,最終,這段代碼將在日志文件中寫入“This is a test0 1 2 3 4 5 6 7 8 9”。
StringBuilder sb = newStringBuilder(“This is a test”);
for (int i=0; i<10; i++) {
   sb.append(i);
    sb.append(”“);
}
log.info(sb.toString());
正如在代碼片段中看到的那樣,你能夠?qū)tring的第一個(gè)元素供給給結(jié)構(gòu)辦法。這將創(chuàng)立一個(gè)新的StringBuilder,新的StringBuilder包括供給的String和16個(gè)額定字符的容量。當(dāng)你向StringBuilder增加更多字符時(shí),JVM將動(dòng)態(tài)增加StringBuilder的巨細(xì)。
如果你現(xiàn)已知道你的String將包括多少個(gè)字符,則能夠?qū)⒃摂?shù)字供給給不同的結(jié)構(gòu)辦法以實(shí)例化具有界說容量的StringBuilder。這進(jìn)一步進(jìn)步了功率,因?yàn)樗恍枨髣?dòng)態(tài)擴(kuò)展其容量。
6.運(yùn)用+銜接一個(gè)語句中的String
當(dāng)你用Java完成你的第一個(gè)運(yùn)用程序時(shí),可能有人通知過你不該該用+來銜接String。如果你是在運(yùn)用程序邏輯中銜接字符串,這是正確的。字符串是不可變的,每個(gè)字符串的銜接成果都存儲(chǔ)在一個(gè)新的String目標(biāo)中。這需求額定的內(nèi)存,會(huì)減慢你的運(yùn)用程序,特別是如果你在一個(gè)循環(huán)內(nèi)銜接多個(gè)字符串的話。
在這些狀況下,你應(yīng)該遵從技巧5并運(yùn)用StringBuilder。
可是,如果你僅僅將字符串分紅多行來改進(jìn)代碼的可讀性,那狀況就不一樣了。
Query q = em.createQuery(“SELECTa.id, a.firstName, a.lastName ”
+ “FROMAuthor a ”
+ “WHEREa.id = :id”);
在這些狀況下,你應(yīng)該用一個(gè)簡略的+來銜接你的字符串。Java編譯器會(huì)對(duì)此優(yōu)化并在編譯時(shí)履行銜接。所以,在運(yùn)轉(zhuǎn)時(shí),你的代碼將只運(yùn)用1個(gè)String,不需求銜接。
7.盡可能運(yùn)用基元
防止任何開支并進(jìn)步運(yùn)用程序功用的另一個(gè)簡潔而快速的辦法是運(yùn)用根本類型而不是其包裝類。所以,最好運(yùn)用int來替代Integer,運(yùn)用double來替代Double。這答應(yīng)JVM將值存儲(chǔ)在倉庫而不是堆中以削減內(nèi)存耗費(fèi),并作出更有用的處理。
8.試著防止BigInteger和BigDecimal
已然我們在評(píng)論數(shù)據(jù)類型,那么我們也快速閱讀一下BigInteger和BigDecimal吧。特別是后者因其精確性而遭到我們的歡迎??墒沁@是有價(jià)值的。
BigInteger和BigDecimal比簡略的long或double需求更多的內(nèi)存,并且會(huì)明顯減慢一切核算。所以,你如果需求額定的精度,或許數(shù)字將超越long的規(guī)模,那么最好三思而后行。這可能是你需求更改以處理功用問題的僅有辦法,特別是在完成數(shù)學(xué)算法的時(shí)分。
9.首要查看當(dāng)時(shí)日志等級(jí)
這個(gè)主張應(yīng)該是清楚明了的,但不幸的是,許多程序員在寫代碼的時(shí)分都會(huì)大多會(huì)疏忽它。在你創(chuàng)立調(diào)試音訊之前,一直應(yīng)該首要查看當(dāng)時(shí)日志等級(jí)。不然,你可能會(huì)創(chuàng)立一個(gè)之后會(huì)被疏忽的日志音訊字符串。
這里有兩個(gè)不和比如。
// don’t do this
log.debug(“User [” + userName + “] called method X with [” + i + “]”);
// or this
log.debug(String.format(“User [%s] called method X with [%d]”, userName, i));
在上面兩種狀況中,你都將履行創(chuàng)立日志音訊一切必需的過程,在不知道日志結(jié)構(gòu)是否將運(yùn)用日志音訊的前提下。因而在創(chuàng)立調(diào)試音訊之前,最好先查看當(dāng)時(shí)的日志等級(jí)。
// do this
if (log.isDebugEnabled()){
    log.debug(“User [” + userName + “] called method Xwith [” + i + “]”);
}
10.運(yùn)用Apache Commons StringUtils.Replace而不是String.replace
一般來說,String.replace辦法作業(yè)正常,功率很高,特別是在運(yùn)用Java 9的狀況下??墒?,如果你的運(yùn)用程序需求許多的替換操作,并且沒有更新到最新的Java版別,那么我們?nèi)匀挥斜匾檎腋旌透杏玫奶娲贰?/span>
有一個(gè)備選答案是Apache Commons Lang的StringUtils.replace辦法。正如Lukas Eder在他最近的一篇博客文章中所描繪的,StringUtils.replace辦法遠(yuǎn)勝Java 8的String.replace辦法。
并且它只需求很小的改動(dòng)。即增加Apache Commons Lang項(xiàng)目的Maven依靠項(xiàng)到運(yùn)用程序pom.xml中,并將String.replace辦法的一切調(diào)用替換為StringUtils.replace辦法。
// replace this
test.replace(“test”,“simple test”);
// with this
StringUtils.replace(test, “test”,“simple test”);
11.緩存貴重的資源,如數(shù)據(jù)庫銜接
緩存是防止重復(fù)履行貴重或常用代碼片段的盛行處理計(jì)劃??偟乃悸泛芎喡裕褐貜?fù)運(yùn)用這些資源比重復(fù)創(chuàng)立新的資源要廉價(jià)。
一個(gè)典型的比如是緩存池中的數(shù)據(jù)庫銜接。新銜接的創(chuàng)立需求時(shí)刻,如果你重用現(xiàn)有銜接,則能夠防止這種狀況。
你還能夠在Java言語自身找到其他比如。例如,Integer類的valueOf辦法緩存了-128到127之間的值。你可能會(huì)說創(chuàng)立一個(gè)新的Integer并不是太貴重,可是因?yàn)樗31贿\(yùn)用,以至于緩存最常用的值也能夠供給功用優(yōu)勢。
可是,當(dāng)你考慮緩存時(shí),請記住緩存完成也會(huì)發(fā)作開支。你需求花費(fèi)額定的內(nèi)存來存儲(chǔ)可重用資源,因而你可能需求辦理緩存以使資源可拜訪,以及刪去過期的資源。
所以,在開端緩存任何資源之前,請保證施行緩存是值得的,也就是說有必要足夠多地運(yùn)用它們。
總結(jié)
正如你所看到的,有時(shí)不需求太多作業(yè)就能夠進(jìn)步運(yùn)用程序的功用。本文中的大部分主張只需求你稍作盡力就能夠?qū)⑺鼈冞\(yùn)用于你的代碼。
可是,最重要的仍是那些與是什么編程言語無關(guān)的技巧:
在你知道必要之前不要優(yōu)化
運(yùn)用剖析器查找真實(shí)的瓶頸
首要處理最大的瓶頸


免费视频观无码一区,国内精品一区二区无码,99精品无码视频在线播放,ā片国产在线播放