本文目錄一覽:
提高Java性能的幾個高效用法
1、調整垃圾收集(GC)
由於垃圾收集的複雜性,很難發現你的應用的準確性能。不過,如果你真的想優化你的應用,你應該相應地處理垃圾收集。通用的準則是調整GC設置並同時執行性能分析。
一旦你對結果感到滿意,你可以停止該過程並尋求其他優化方式。確保除了在平均事務處理時間之外,你還留心了異常值。這些異常值是造成Java應用緩慢的真正的罪魁禍首並且很難找到。
此外,你要明白應用運行期間性能下降的效應。在每單個cpu時鐘內的緩慢操作是可以忽略的,但在每單個數據庫事務中的緩慢操作則是非常昂貴的消耗。但是你應該根據性能短板選擇你的優化策略,並應該根據工作負載來優化應用。
2、正確地選擇適合你的GC算法
讓我們更深入地探討GC優化。畢竟,GC優化是要處理的整個優化問題中最基本的。目前,Java中有四種供你選擇的垃圾收集算法。每種算法滿足不同的需求,因此你要選擇(適合你的需求的)。很多開發人員正是因為不了解GC算法而未能優化他們的應用。
這四個算法分別是串行回收器,並行/吞吐量回收器,CMS回收器和G1回收器。想要了解更多關於每種垃圾收集器的信息及它們是如何工作的,請查看這篇來自Takipi博客的非常棒的文章Garbage Collectors—Serial vs。 Parallel vs。 CMS vs。 G1。這篇文章同時還討論了Java8對GC算法的影響及其他細節上的改變。讓我們再回到GC算法上,根據Understanding Java Garbage Collection這篇文章所述,並發標記和清除GC(即」CMS」)算法才是適合網絡服務端應用的最佳算法。並行GC算法適合那些內部可預測的應用。
G1和CMS是並發操作的理想選擇,但仍然會引起(應用)頻繁停頓。實際的選擇取決於你如何取捨。舉例來說,儘管選擇並行算法會帶來更長的GC停頓時間,但相較於其他GC算法,選擇並行算法仍是一個好主意。
3、Java堆
Java內存堆在迎合內存需求方面擔任了至關重要角色。通常更好的做法是初始時分配最小的堆,然後通過持續的測試不斷增加它的大小。大多數時候優化問題都可以通過增加堆的大小解決,但如果存在大量的GC開銷,則該解決方案不起作用。
GC開銷還會使吞吐量急劇下降,進而使得應用難以形容的慢。此外,及早調整GC可以幫助你避免堆大小分配的問題。開始的時候,你可以選擇任何1GB到8GB的堆大小。當你選擇正確的堆大小,老生代和新生代對象的概念也就不需要了。總而言之,堆大小應該取決於老生代和新生代對象的比率,之前的GC優化和對象集合(即所有對象佔用的內存大小)。
4、關鍵應用優化
關鍵代碼優化是優化你的Java應用最好的方式。如果你的應用對GC和堆優化沒有反應,那麼最好是做架構改進並關注於你的應用是如何處理信息的。使用聰明的算法並管理好對象就能解決大量的問題,包括內存碎片,堆大小問題和垃圾收集的問題。
5、使用最優的函數
Java提供了多個函數來提升算法效率。如果你使用StringBuilder代替簡單的String,你可以得到微乎其微的性能提升。不過,我們還有其他方式在代碼層面進行優化。讓我們看看下面這些優化方法。
使用StringBuilder代替+操作符。
避免使用iterator。
多使用棧帶來的好處。
避免使用正則表達式,使用Apache Commons Lang作為代替。
遠離遞歸。遞歸會佔用大量資源!
看完阿里程序員做JVM調優,讓我明白12K和40K的差距在哪
怎樣才能做好性能調優?
關於性能調優,我先來說說的我的感受。Java性能調優不像是學一門編程語言,無法通過直線式的思維來掌握和應用,它對於工程師的技術廣度和深度都有着較高的要求。
互聯網時代,一個簡單的系統就囊括了應用程序、數據庫、容器、操作系統、網絡等技術,線上一旦出現性能問題,就可能要你協調多方面組件去進行優化,這就是技術廣度;而很多性能問題呢,又隱藏得很深,可能因為一個小小的代碼,也可能因為線程池的類型選擇錯誤..可歸根結底考驗的還是我們對這項技術的了解程度,這就是技術深度。
顯然,性能調優不是一件容易的事。但有沒有什麼方法能把這件事情做好呢?
在這篇文章里,將從實戰出發,精選高頻性能問題,透過 Java 底層源碼,提煉出優化思 路和它背後的實現原理,最後形成一套「學完就能用的調優方法論」。這也是很多一線大廠 對於高級工程師的要求,希望通過這個文章幫助你快速進階。
Java調優
性能調優策略圖
設計調優
JVM調優
多線程調優
數據庫調優
Java程序優化
並行程序開發及優化
Java性能調優工具
實戰演練場
最後
這篇文章適合所有Java程序員、軟件設計師、架構師以及軟件開發愛好者,對於在一定經驗的java工程師,更能幫助突破技術瓶頸,深入Java內核開發!
希望本文能夠在工作中對讀者有所幫助。
jvm性能調優都做了什麼
JVM是最好的軟件工程之一,它為Java提供了堅實的基礎,許多流行語言如Kotlin、Scala、Clojure、Groovy都使用JVM作為運行基礎。一個專業的Java工程師必須要了解並掌握JVM,接下來就給大家分享Java基礎知識中JVM調優相關知識點。
杭州Java基礎知識學習之JVM調優講解
JVM常見的調優參數包括:
-Xmx:指定java程序的最大堆內存, 使用java -Xmx5000M -version判斷當前系統能分配的最大堆內存;
-Xms:指定最小堆內存, 通常設置成跟最大堆內存一樣,減少GC;
-Xmn:設置年輕代大小。整個堆大小=年輕代大小+年老代大小。所以增大年輕代後,將會減小年老代大小。此值對系統性能影響較大,Sun官方推薦配置為整個堆的3/8;
-Xss:指定線程的最大棧空間, 此參數決定了java函數調用的深度, 值越大調用深度越深, 若值太小則容易出棧溢出錯誤(StackOverflowError);
-XX:PermSize:指定方法區(永久區)的初始值,默認是物理內存的1/64,在Java8永久區移除, 代之的是元數據區,由-XX:MetaspaceSize指定;
-XX:MaxPermSize:指定方法區的最大值, 默認是物理內存的1/4,在java8中由-XX:MaxMetaspaceSize指定元數據區的大小;
-XX:NewRatio=n:年老代與年輕代的比值,-XX:NewRatio=2, 表示年老代與年輕代的比值為2:1;
-XX:SurvivorRatio=n:Eden區與Survivor區的大小比值,-XX:SurvivorRatio=8表示Eden區與Survivor區的大小比值是8:1:1,因為Survivor區有兩個(from, to)。
JVM實質上分為三大塊,年輕代(YoungGen),年老代(Old Memory),及持久代(Perm,在Java8中被取消)。
年輕代大小選擇
響應時間優先的應用:儘可能設大,直到接近系統的最低響應時間限制(根據實際情況選擇)。在此種情況下,年輕代收集發生的頻率也是最小的。同時,減少到達年老代的對象。
吞吐量優先的應用:儘可能的設置大,可能到達Gbit的程度。因為對響應時間沒有要求,垃圾收集可以並行進行,一般適合8CPU以上的應用。
年老代大小選擇
響應時間優先的應用:年老代使用並發收集器,所以其大小需要小心設置,一般要考慮並發會話率和會話持續時間等一些參數。如果堆設置小了,可以會造成內存碎片、高回收頻率以及應用暫停而使用傳統的標記清除方式;如果堆大了,則需要較長的收集時間。最優化的方案,一般需要參考以下數據獲得:並發垃圾收集信息、持久代並發收集次數、傳統GC信息、花在年輕代和年老代回收上的時間比例。
減少年輕代和年老代花費的時間,一般會提高應用的效率。
吞吐量優先的應用:一般吞吐量優先的應用都有一個很大的年輕代和一個較小的年老代。原因是,這樣可以儘可能回收掉大部分短期對象,減少中期的對象,而年老代盡存放長期存活對象。
較小堆引起的碎片問題
因為年老代的並發收集器使用標記、清除算法,所以不會對堆進行壓縮。當收集器回收時,他會把相鄰的空間進行合併,這樣可以分配給較大的對象。但是,當堆空間較小時,運行一段時間以後,就會出現「碎片」,如果並發收集器找不到足夠的空間,那麼並發收集器將會停止,然後使用傳統的標記、清除方式進行回收。如果出現「碎片」,可能需要進行如下配置:
-XX:+UseCMSCompactAtFullCollection:使用並發收集器時,開啟對年老代的壓縮。
-XX:CMSFullGCsBeforeCompaction=0:上面配置開啟的情況下,這裡設置多少次Full GC後,對年老代進行壓縮。
java怎麼高效調優接口
本來用DWR調用方法就是多線程的,線程總數與J2EE容器配置的有關。建議如下:如果你這個A()調用的接口一次只允許一個訪問,那麼需要在A所在的類里設置一個靜態成員變量,如staticStringobject=”some”。然後在A()方法一開始用synchronized(object)把代碼都包含進來。這樣可以確保一次只有一個訪問。如果接口一次最多運行固定數目的訪問,如10個。那麼複雜一些,不過我估計你不是這個情況。一般建議這個固定數目與J2EE容器配置的線程數一致即可。上述方法都是為了防止接口被同時訪問,但這樣的後果就是前端用戶會等待,甚至線程滿。前端等待是沒法的,後面慢,前面只有排隊了。線程滿的話,最好的方式是採用非阻塞的IO(NIO),不過那個很難做到。你提出的10秒終止方法是一種方案,不過關鍵在於如何終止一個方法的運行。很遺憾,Java不能任意終止一個方法的運行,不過對於接口操作,可以如下處理:a)如果接口是TCP/IP,那麼可以通過強行關閉socket來終止。如:timer.schedule(newTimerTask(){publicvoidrun(){socket.close();}},10000);b)如果接口是用類庫的話,看看它有沒有設置timeout的地方,如果有,那麼設置一下,如果沒有,那麼沒法了。補充:你用了axis的setTimeout,理論上超過10秒後call.invoke會拋出異常的。假設後台很慢,每次都需要10秒,假設weblogic線程池大小為50,那麼如果同時訪問的人超過50個,或者每秒訪問量超過5個,那麼就會發生線程阻塞。這是系統性能問題,可以將weblogic的線程池最大數量設置高些來增加吞吐量。不過這種方式治標不治本,如果你的程序預計到並發訪問量很大,那麼後台響應超過1秒就不太合理了,這個改動起來就很麻煩了。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/309490.html