效能最佳化總結:一個任務對資料庫頻繁操作,並且大量發送訊息。時間暴長!
0. socket異常,rmi調用中傳遞大量資料出錯、系統處理資料越來越慢。測試後發現預設最大記憶體僅僅64M, -Xmx加大記憶體。
1. hibernate 問題1: 資料第一次修改後儲存成功,第二次修改不儲存. 跟蹤hibernate後發現,flush認為資料在第二次修改後沒有變化。俺們儲存的對象中有個map屬性,被定義為user type,映射到string. 因為是POJO,所以hibernate在判斷對象有沒有變化的時候取了所有屬性列表,這個map是引用,比較前後都是它,看不出變化。如果用個新map就OK了,但是這樣重新構造map消耗比較大,乾脆直接把序列化以後的string作為屬性,原來的map作為@Transient.
問題2: 改過之後效能還是不高,從log看,讀取到的對象沒做任何修改也會被flush到資料庫。再跟蹤發現對象沒做任何修改也會變化map string也會變化,仔細跟蹤發現原來hash map無序,所以轉換後string不一樣,低級錯誤。用效能測試工具發現這個新的map轉string屬性被頻繁調用,這個轉換本來就比較耗時。解決辦法,把轉換做成lazy的,map有變化後才轉換,轉換後緩衝之。 問題3: 頻繁讀取資料庫。同樣查詢有的作了很多次,應該緩衝。query.setCacheable(true);加上後沒效果,再跟蹤發現hibernate.cache.use_query_cache沒有設定為true 問題4: 資料庫事務加上、MO設定讀緩衝。
2. jms 發現JMS訊息頻繁產生線程來發送訊息,對任務加上JMS事務後,在任務結束後一次發送。 activemq自己提供了串連池,用上3. 低效的代碼: 很多方法很簡單,但是在幾萬甚至上百萬次調用後,很耗時。不必要的不要split, 有些可以簡單去subString解決,需要的可以考慮apache的StringUtils.split(string,char),頻繁split的可以緩衝結果。 有些對象註定不會重複,equals()方法直接比較引用。 複雜不常用對象可以lazy init4. 大量訊息導致介面沒有響應 在接收到大量訊息後,swing線程被大量SwingUtilities.invokeLater堵塞隊列,使用者事件不響應。考慮採用InvokeAndWait(), 發現效率不高。後來在每接收到幾十個訊息後主動調用空的InvokeAndWait(),這樣保證螢幕不死掉。 測試第三方API的響應速度,發現有些需要改進的地方。
5. javax.jms.JMSException: start failed: No buffer space available (maximum connections reached?): recv failed 好像是串連不足,關掉一些網路程式後會好些,懷疑防火牆、sp2的串連限制(crack後好像沒用) 其它: 演算法上的最佳化,不發送無用訊息,減少不必要的資料庫訪問,盡量一次批量讀取資料。
最佳化後的已耗用時間由分鐘層級降到秒級,比較滿意。