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