java效能優化
目錄
基準測試和JIT
即便是單執行緒的基準測試用例,變數也要申明成 volatile型別的,這樣可以防止編譯器做優化
要加入一定的熱身期
監控命令
jcmd 列印java程式所涉及的基本類,執行緒和VM資訊
jconsole
jhat,讀取記憶體堆轉儲,並有助於分析
jmap,提供堆轉儲和其他JVM記憶體使用的資訊
jinfo,檢視JVM的系統屬性,可以動態設定一些系統屬性
jstack
jstat
jvisualvm
比如
jcmd [process_id] VM.system_properties
或者 jinfo -sysprops [process_id]
jcmd [process_id] VM.version
jcmd [process_id] VM.command_line
jcmd [process_id] VM.flags [-all]
列印所有的調優標誌
java other_options -XX:+PrintFlagsFinal -version
jstack [process_id]
或者 jcmd [process_id] Thread.print
關閉某個屬性
jinfo -flag -PrintGCDetails [process_id]
可以在執行期間設定屬性開啟/關閉,但不是所有屬性都支援熱關閉/開啟的
Java Mission Control 商業監控工具,其關鍵特性是java飛行記錄器(Java Flight Recorder)
GC相關
GC輸出
-verbose:gc
-XX:+PrintGC
-XX:+PrintGCDetails
-XX:+PrintGCTimestamps
-XX:+PrintGCDateStamps
-Xloggc:filename
-XX:+UseGCLogfileRotation
-XX:+NumberOfGCLogfiles
Througput GC演算法是一種空間和時間的權衡
開始時可以用預設的自適應方式
如果把暫停時間設定的太短,就會觸發更頻繁的GC,會導致吞吐量下降
如果把GC比率設定太低,也會導致堆空間變小,更可能會頻繁觸發GC
有兩個相關的引數
-XX:MaxGCPauseMillis=N
-XX:GCTimeRatio=N
Through收集器
分為Minor GC,Full GC
暫停時間越短GC就會越多,GC次數減少意味著時間增大堆空間增加
對through調優是一種取捨
CM收集器
初始標記,併發標記,預清理,重新標記,併發清理,(清理失敗)
增量式CMS垃圾收集器,在單CPU上會增加CPU負擔,增量收集採用間歇性的方式收集,1.8之後被廢棄
G1收集器
初始標記,併發標記,預清理,重新標記,併發標記
分成2048個region
新生代+老年代 混合收集模式
併發模式失敗(類似CMS),疏散失敗(Srvivor和老年代沒有空間容納倖存物件)
調整後臺收集執行緒數
調整垃圾收集器執行頻率(預設佔到45%時回收)-XX:InitiatingHeapOccupancyPercent=N
調整混合垃圾收集週期
分割槽預設為35%時啟動收集 -XX:G1MixedGCLiveThresholdPercent
最大混合式GC週期數,可解決晉升失敗問題,但會增加GC週期停頓時間,-XX:G1MixedGCCountTarget=N
最大停頓時間 -XX:MaxGCPauseMillis
晉升調整
-XX:MinSurvivorRatio=N
-XX:InitialTenuringThreshold=N
-XX:TargetSurvivorRatio
-XX:+AlwaysTenure
-XX:+NeverTenure
分配大頁
-XX:+UseTLAB
-XX:TLABWasteTargetPercent=N
-XX:TLABWasteIncrement=N
-XX:G1HeapRegionSize=N
堆記憶體
記憶體溢位錯誤
1.原生記憶體不足
Exception in thread "main" java.lang.OutOfMemoryError
unable to create new native thread
2.永久代或元空間記憶體不足
Exception in thread "main" java.lang.OutOfMemroyError: PermGen space
3.堆記憶體不足
Exception in thread "main" java.lang.OutOfMemoryError: java heap space
4.達到GC的開銷限制
Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
-XX:+UseGCOverheadLimit 如果超過了這個設定值,比如預設98%的時間用在GC上
-XX:+GCHeapFreeLimit 如果釋放的記憶體少於這個指標,預設是2%,釋放的記憶體不足堆的2%
減少記憶體使用
減少物件大小
延遲物件初始化
不可變物件
字串保留 intern()
物件重用
1.執行緒池
2.JDBC池
3.EJB池
4.大陣列
5.原生NIO緩衝區
6.安全相關類
7.字串編解碼器物件
8.StringBuilder協助者
9.從NDS查詢到的名字
10.ZIP編解碼器
弱引用,軟引用,幻引用
Finalizer
原生記憶體
記憶體佔用最小化
1.堆
2.執行緒棧
3.程式碼快取
4.直接位元組緩衝區
原生記憶體跟蹤
jcmd [process_id] VM.native_memory summary
-XX:NativeMemoryTracking=off|summary|detail
原生NIO快取
-XX:MaxDirectMemorySize
大頁
+XX:+UseLargePages
+XX:LargePageSizeInBytes
指標壓縮
+XX:+UseCompressedOops
jcmd 11674 VM.native_memory summary
11674:
Native Memory Tracking:
Total: reserved=1573497KB, committed=36193KB
- Java Heap (reserved=253952KB, committed=16384KB)
(mmap: reserved=253952KB, committed=16384KB)
- Class (reserved=1056875KB, committed=4971KB)
(classes #389)
(malloc=107KB #122)
(mmap: reserved=1056768KB, committed=4864KB)
- Thread (reserved=10304KB, committed=10304KB)
(thread #11)
(stack: reserved=10260KB, committed=10260KB)
(malloc=33KB #52)
(arena=12KB #20)
- Code (reserved=249631KB, committed=2567KB)
(malloc=31KB #295)
(mmap: reserved=249600KB, committed=2536KB)
- GC (reserved=839KB, committed=71KB)
(malloc=7KB #79)
(mmap: reserved=832KB, committed=64KB)
- Compiler (reserved=132KB, committed=132KB)
(malloc=1KB #22)
(arena=131KB #3)
- Internal (reserved=203KB, committed=203KB)
(malloc=171KB #1206)
(mmap: reserved=32KB, committed=32KB)
- Symbol (reserved=1356KB, committed=1356KB)
(malloc=900KB #64)
(arena=456KB #1)
- Native Memory Tracking (reserved=32KB, committed=32KB)
(malloc=2KB #29)
(tracking overhead=30KB)
- Arena Chunk (reserved=171KB, committed=171KB)
(malloc=171KB)
執行緒
執行緒池ThreadPoolExecutor設定
1.最小任務數
2.最大任務數
3.任務佇列,有界佇列,無界佇列
ForkJoinPool
使用map-reduce原理
如果整個待執行的任務是均衡的用ThreadPoolExecutor更好
否則用ForkJoinPool更好
竊取雙端佇列
同步的方式
volatile
CAS
原生同步
競爭不大用CAS,競爭比較多用原生同步
Amdahl定律
volatile導致的偽共享會讓效能急劇下降
偏向所,優先處理訪問頻繁的執行緒
自旋鎖,JDK8廢棄
JavaEE相關
減少輸出,包括減少空格
合併CSS和JavaScript
壓縮輸出
不要使用JSP動態編譯
減少會話中保留的資料,減少會話時間
servlet可能有專門的執行緒池,EJB也有專門的執行緒池,同樣JMS也是
EJB bean的執行過程
1.建立EJB
2.處理註解並且將依賴的資源注入這個新的EJB物件
3.呼叫註解為@PostConstruct的函式
4.如果是有狀態bean,呼叫註解為@Init的函式或者ejbCreate()函式
5.執行業務方法
6.呼叫任何註解為@PreRemove的函式
7.如果是有狀態bean,則呼叫remove()函式
EJB池化後,只需要執行業務方法,其他初始化銷燬的都可以不做
有狀態bean的鈍化(Passivation),儘量避免這麼做
及時在一個伺服器中,本地介面也比遠端介面快,因為少了序列化/反序列化步驟
所有遠端EJB都必須支援IIOP(CORBA)協議
Web Service使用JAX-WS
RESTful使用JAX-RS
XML和Json的解析方式,XML的驗證會影響很大效能
建立JAXB物件比建立DOM物件昂貴,但JAXB寫XML速度要快於DOM物件
Serializable標記介面
Externalizable自定義序列化介面(包含readExternal和writeExternal)
序 號 |
區 別 |
Serializable |
Externalizable |
1 |
實現複雜度 |
實現簡單,Java對其 有內建支援 |
實現複雜, 由開發人員自己完成 |
2 |
執行效率 |
所有物件由Java統一儲存, 效能較低 |
開發人員決定哪個物件儲存, 可能造成速度提升 |
3 |
儲存資訊 |
儲存時佔用空間大 |
部分儲存, 可能造成空間減少 |
在一般的開發中,因為Serializable介面的使用較為方便,所以出現較多
JDBC驅動程式型別1-4,四種
PrepareStatment可以重用sql語句,比Statement效能更好
預處理語句必須依靠單個連線進行池化,而預處理語句會消耗大量堆空間
資料庫查詢返回的取捨,頻繁的呼叫資料庫每次取一小部分,或者一次取很多但會造成GC
Container Mnaged Transactions CMT 使用容器管理事務
User Managed Transaction UMT 使用使用者管理事務
XA事務
減少寫入的欄位,不必要跟新的不寫
延遲載入大型欄位
不太容易衝突的使用樂觀鎖,經常發生衝突的使用悲觀鎖
加入JPA快取
Java SE 相關
I/O緩衝區,socket I/O也需要緩衝
ClassLoader的雙親委派模型,多執行緒建立類時候會有影響效能,1.7之後改為並行模式效能提升
ClassLoader使用loadClass()尋找類,如果找不到呼叫findClass(),我們自己的類載入只需實現findClass即可
-XX:+AlwaysLockClassLoader 還原為JDK6的持有鎖的類載入模式
Random 執行緒安全的
ThreadLocalRandom 實現方式類似Random,一種偽隨機數
SecureRandom,獲得了更多的隨機數實現確保更安全,如果無法獲取更多隨機數可能會等待好幾秒
現在的JNI未必比Java程式碼更快了,若一定要使用應限制Java到C的呼叫次數,這會影響效能
現在的JVM處理異常速度也很快了,但獲取異常棧資訊(尤其棧很深)會損耗效能
防禦性程式碼比丟擲異常更好
可以用 -XX:-StrackTraceInThrowable 禁止生成異常棧資訊(不推薦)
String str = "aa"+"bb"+"cc" 編譯器會做優化
str += "aa";
str += "bb";
會變成
str = new StringBuilder(str).append("aa");
str = new StringBuilder(str).append("bb");
Java集合類
執行緒安全的集合
設定集合的大小,IO類中的ByteArrayOutuptStream也是類似的
ConcurrentHashMap
AggressiveIpts 會在啊一些基本的類中開啟某些優化,導致一些副作用
AutoBoxCacheMax 自己裝箱cache
lambda效能並不差,可能比匿名類效能更好
應該從方便程式設計的角度出發,因為效能上沒什麼差別
list.stream().filter(s->s.charAt(0)!='A').(s->s.charAt(1)!='A').(s->s.charAt(2)!='A').(s->s.charAt(3)!='A')
過濾器會先判斷最後一個
(s->s.charAt(3)!='A')
拿到資料之後交給倒數第二個,然後倒數第三個。。。
過濾器的效能比迭代器好,因為能少處理很多資料
但多個過濾器會有開銷,實現時需要注意
參考
詳解 JVM Garbage First(G1) 垃圾收集器
相關文章
- JAVA效能優化思路探究Java優化
- 【Java效能優化思路方向】Java優化
- [java][效能優化]java高階開發必會的50個效能優化Java優化
- 怎麼做好Java效能優化Java優化
- 《java學習三》jvm效能優化-------調優JavaJVM優化
- 【前端效能優化】vue效能優化前端優化Vue
- 《java學習三》jvm效能優化------jconsulJavaJVM優化
- 【推薦】Java效能優化系列集錦Java優化
- 推薦:Java效能優化系列集錦Java優化
- Java 效能優化之——效能優化的過程方法與求職面經總結Java優化求職
- 效能優化優化
- Java 執行緒與同步的效能優化Java執行緒優化
- 前端效能優化(JS/CSS優化,SEO優化)前端優化JSCSS
- Android效能優化——效能優化的難題總結Android優化
- [效能優化]DateFormatter深度優化探索優化ORM
- 前端效能優化 --- 圖片優化前端優化
- 效能優化|Tomcat 服務優化優化Tomcat
- Android 效能優化 ---- 啟動優化Android優化
- Android效能優化----卡頓優化Android優化
- Javascript 效能優化JavaScript優化
- react效能優化React優化
- Canvas效能優化Canvas優化
- UI效能優化UI優化
- mongodb效能優化MongoDB優化
- Android效能優化Android優化
- EF效能優化優化
- TableView效能優化View優化
- web效能優化Web優化
- mysql效能優化MySql優化
- MySQL——效能優化MySql優化
- Redis 效能優化Redis優化
- python效能優化Python優化
- 效能優化有感優化
- javascript效能優化JavaScript優化
- javasciprt效能優化Java優化
- php效能優化PHP優化
- 效能優化篇優化
- React 效能優化React優化