程式者的胡言亂語

pageicon 星期五 十一月 03, 2006

找出Java程式吃掉CPU的元兇

Java應用程式的效能問題大致上以三種為主:執行的太慢、佔據太多的CPU時間、佔用太多的記憶體。執行的太慢不一定會佔去太多的CPU時間,因為執行的慢,有可能是因為I/O動作所導致的。而佔去太多的CPU時間有可能讓系統變慢,但不一定會引發明顯變慢的感覺,因為大多數的程式都不那麼需要CPU


之前曾提到Busy Loop,就是在loop裡做了CPU intensive的活動,導致程式佔用極多的CPU時間,時常都是9x%以上。這就是一個佔去太多CPU時間的例子。


前幾天我們試著要解決一個上線系統的效能問題。這個系統並沒有表現出反應時間太慢的情況,但CPU使用率持續高居不下,所以得試著加以解決。


我們手邊沒有什麼效能量測或調校的工具,所以只好試著土法煉鋼。其實效能調校的程序都很固定:


步驟1:進行效能量測,也就是profiling


步驟2:找出效能瓶頸


步驟3:針對效能瓶頸進行改善


步驟4:回到步驟1,重覆這個程序,直到沒有明顯的效能瓶頸為止


很明顯的,我們會需要一個量測的工具。你可以記錄每一段程式碼的執行起迄時間點,但那只能用來知道總共的執行時間,卻不能知道在這段時間內,這段程式碼真正被分配到的CPU時間有多少。為此,我們得有個工具才行。


我找到一篇文章:Profiling CPU usage from within a Java application,在這篇文章中,利用JNI使用Wi32既有的API來取得程式執行的CPU時間。由於我們的平台恰好就在Win32上,所以直接使用在這篇文章中開發的程式庫


接下來就只要量測各個執行點究竟佔用了CPU使用率就可以了。






final SystemInformation.CPUUsageSnapshot s1 = SystemInformation.makeCPUUsageSnapshot();


final SystemInformation.CPUUsageSnapshot s2 = SystemInformation.makeCPUUsageSnapshot();


double d = SystemInformation.getProcessCPUUsage(s1, s2);


它提供多個classes,但其實只要SystemInformation這個class就可以了。如果要量測在你的程式中的兩個執行點之間共佔用了多少CPU使用率,只要分別在這兩個執行點上照一份快照(makeCPUUsageSnapshot()),接著使用getProcessCPUUsage()就可以算出在這兩個執行點之間,共佔用了多少百分比的CPU使用率。


安置拍照的地點是一個需要注意的事項。由於你不那麼明確知道元兇究竟在何處,所以在第一輪安置拍照點時,拍照點總共涵蓋的範圍會很廣,但間隔卻很大。但第一輪洗出照片後,你會知道元兇究竟落在那兩個點之間,接著再進行第二輪,在找出的兩點之間,再安置更細的拍照點,依此遞迴下去,最終就會找到元兇,基本上這就像是binary search的方式。


其實效能瓶頸的位置,往往有時叫人驚訝,我們找到的地方竟然是一段使用JAAS的程式碼。透過一些caching的技巧,這個瓶頸就解除了。原本CPU使用率時常高居在70%-99%的系統,立即降到1%以下。


所以我覺得這個程式庫其實滿適合窮人使用的-當你買不起昂貴的效能量測工具時,土法煉鋼也不錯。


這個程式庫也沒有什麼內容,主要就是利用GetProcessTimes()這個Win32 API來達成,倘若要在其他的平台上使用,就得試著把JNI的部份移植到其他平台上了。

迴響:

發表迴響:
  • HTML 語法: 關閉
把對母乳媽媽的感謝與支持傳出去

« 八月 2014
星期日星期一星期二星期三星期四星期五星期六
     
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
      
今日

Search this blog

Links

Weblog menu

Today's referrers

Feeds