摘要:目前,Linux網絡計算機中的Java虛擬機在運行Java應用程序時,存在著執行性能較低的問題。該文實現一種優化方案:在Kaffe虛擬機中應用并改良直接線索式解釋器優化技術。旨在兼顧Linux NC現有的硬件配置和軟件模式,有效地提升Java虛擬機運行效率,并保證較低的CPU和內存成本。從而改善虛擬機的性能表現。
關鍵詞:Linux;NC;Kaffe;Java虛擬機;性能優化
NC(Network Computer)是網絡計算體系結構演變的必然結果。NC系統軟件包括兩大部分:運行在NC上的NCOS和運行在應用服務器上的NCServer。Java虛擬機(Java Virtual Machine)是兩大部分的重要組件,其設計、實現技術將影響Java應用程序執行的實際效果及NC中其它服務的性能表現。
1 網絡計算機中JVM的性能表現
目前,隨著多種性能優化技術在JVM中的應用,Java在桌面操作系統及服務器中的運行效率有了很大程度的提高。但嵌入式領域的JVM性能的研發工作卻滯留在起步階段。Linux NC應用的是桌面OS的JVM。雖然這種JVM的優化技術大大提高了Java的執行性能,但嵌入式設備NC的計算及存儲能力卻難以負擔這種JVM的技術對CPU、內存的較高要求。
2 基于Linux NC的JVM性能優化方案
Linux成為繼Windows CE之后,第2個應用于NC的主流操作系統。因此,本文的優化工作將基于Linux平臺。
2.1優化對象
源代碼開放的軟件包Kaffe是一個優秀的Java語言環境。優化方案選擇Kaffe作為優化對象,主要基于4個原因:Kaffe是基于類Unix系統上開發的,特別是Linux和Free BSD。因此,把Kaffe移植到支持POSIX原語的體系結構比其它體系結構容易;Kaffe是一個完整的遵從Personal Java 1.1規范的Java語言環境,可以應用于各種因特網設備、嵌入式系統;Kaffe的解釋器采用switch-case模式,性能相對較低;Kaffe基于模塊實現,具有伸縮性和高效性。
2.2 技術選擇
鑒于上述優化技術的特點,作者分析得出編譯執行技術與NC的不適用性,主要表現在:
在800MHz工作頻率,32位的總線寬度的CPU下,編譯執行的Java程序會呈現較明顯的停滯現象;
NC的CPU Cache容量難以容納全部的核心代碼,使得CPU訪問內存的機率增加,JVM的執行效率降低;
編譯產生的機器代碼量是原字節碼的幾倍到幾十倍,NC的內存和CPU Cache難以承受。
因此,解釋執行技術更適合Linux終端設備。由于:
解釋執行的JVM占用較小的ROM;字節碼占用較小內存空間,減輕了對數據Cache的壓力;解釋方式運行的JVM的核心代碼量較小,增加了在指令Cache中的比例。
2.3方案設計
根據以上分析結論,及解釋技術的優化技術在嵌入式移動通信領域的應用良好的現狀,本文采用解釋執行技術及其優化手段設計優化方案。
DTI工作機制:轉化函數對應一個translated code數組,函數按順序讀入字節碼指令,查找其解釋程序入口地址,將地址保存在對應的數組中。即原來的操作碼對應轉化為解釋程序的標號地址。
技術的改良。為了節省DTI中translated code數組的空間,方案對數組進行了合理的壓縮。
合并操作數。在32位CPU中,標號地址長度占用4B的存儲器。操作碼后的操作數長度從0B到數10B不等。原來16位和32位的操作數分別占用2B,2個字節碼單元和4B,4個字節碼單元。合并后,它們均占用1個translated code數組單元。
處理跳轉地址。操作數的合并引起了操作碼對應偏移量的變化,因此,需要更新絕對和相對跳轉指令的目標地址。方案引入tcbc_offset數組,令其保存translated code數組相對于原字節碼數組的偏移量的差值(帶符號)。當修改跳轉目標地址時,利用該數組的值分別計算絕對和相對跳轉指令的新目標地址。同時,方案通過3個優化途徑進一步提升DTI的優化
幅度:
①《Java虛擬機規范》只定義了202條指令,其余的可由用戶自定義,即偽指令。
第1類偽指令:用指定數據類型的偽指令替代不指定操作數類型的指令。省去遍歷各種類型常量池的操作。如:ldc指令把常量池中的項壓入Java棧。偽指令intldc,floatldc,stringldc指定具體的數據類型。在轉化字節碼的過程中,根據常量的數據類型,對應到偽指令,直接指向某個類型的常量池。提高了執行效率,減小了字節碼尺寸。
第2類偽指令:將小于等于4個字節的常量值放入translated code數組中操作數的位置,省去查找常量池的操作。
②合并字節碼指令序列在字節碼轉化過程中,可以跟蹤記錄每個Java方法被調用的次數,虛擬機初始化時,首先設定一個默認的調用頻率指標,對調用頻率高于默認值,且最高的Java方法進行連續的字節碼指令合并。將該Java方法的字節碼指令對應的處理程序合并到一個標號地址下,然后修改translated code數組中該Java方法的首標號地址,使其指向新的合并后的地址,并依次轉移操作數,處理操作數指針,以保證操作碼和操作數之間的對應關系,最后釋放剩余的translated code數組。該處理方式既提高了解釋執行的速度,同時再次獲得壓縮translated code數組的效果。
③管理轉化碼數組空間
字節碼轉化為translated code需要付出原字節碼大小的3~4倍的存儲空間的代價。對于內存空間有限的Linux NC來說,需要一種機制高效的利用這塊內存空間。方案根據訪問頻率進行空間淘汰的方法滿足了translated code空間限制的條件。其工作機制:
·開辟translated code的專用內存--Translated Code Block;
·變量accessCount記錄Java方法被調用的次數;
·若當前translated code的內存量不足以存放新的轉化碼時,查找方法表中已轉化的每個Java方法的accessCount值,選擇該值最小的Java方法所對應的translated code進行內存空間釋放。重復該過程直到能容納新的轉化碼為止。
2.4方案實現
(1)數據結構
修改涉及Java類型實例信息和Java方法信息的數據結構,同時為DTI添加新的數據結構。在Translated_code結構體中構建共同體,保存程序處理代碼入口地址或者操作數信息,以及原字節碼的偏移量等其它控制參數。
(2)優化后的執行流程
字節碼解釋模塊和字節碼轉化模塊實現了方案的設計思想。run_translatedMachine()--解釋模塊的主體函數實現了translated code解釋器和switch-case解釋器兩種執行方式。若字節碼轉化過程失敗則采用switch-case模式執行。switch-case解釋完一條字節碼后,根據程序計數器的值,進行下一次switch;translated code解釋完一條字節碼后,直接goto到下一條指令的解釋程序。轉化模塊包含兩個重要函數:translated_method()將字節碼轉化為translated code;manage_tcspace()以Java方法為單位管理轉化后的字節碼。translated_method()通過manage_tcspace()申請轉化碼空間,空間足夠的情況下進入實際的轉化流程。方案的實現通過3個階段完成字節碼轉化、解釋過程:第1階段實現DTI的轉化及操作數的合并;第2階段實現合并字節碼序列;第3階段處理前兩個階段引起的操作碼偏移量的變化,即跳轉指令的更新。
3結論與展望
本文的優化方案主要有以下3個特點:
提高了Kaffe在Linux NC上的執行效率;在技術成本方面,系統資源占用率相對較低,并保證NC產品在Java技術方面原有的支持特性;方案的設計基于模塊化結構,具有清晰、完整的特點,且易于實現和擴展。
該方案雖然已將NC的JVM性能提升到一定水平,但還存在一些值得深入改進的地方。如:方案的轉化字節碼的設計本質上屬于編譯執行方式,因此可應用基于編譯方式的優化技術;對代碼量較小的高頻Java方法進行內嵌,以減小方法調用的開銷。這些技術的實現會使JVM在Linux NC中的表現更加出色!
參考文獻
[1]黃廣君,普杰信,吳慶濤.嵌入式Java虛擬機實現中的代碼優化 [J].河南科技大學學報(自然科學版),2003,24(1):57-60.
[2]李允,羅蕾,雷昊峰,等.嵌入式Java虛擬機的性能優化技術 [J].計算機工程,2004,30(18):47-49.
[3]Venners B.深入Java虛擬機[M].第2版.曹曉鋼,蔣靖,譯.北京:機械工業出版社,2003:31-112.