文/梁成豪
如今,高級(jí)語言(如C語言)已經(jīng)成為大量被應(yīng)用于系統(tǒng)、應(yīng)用軟件的開發(fā)。軟件的性能好壞在對(duì)其進(jìn)行大規(guī)模應(yīng)用時(shí)在設(shè)計(jì)極差的地方可以被宏觀的觀察出來,但是也很難定位到問題所在,即便是可以定位到問題所在,也很難分析得很細(xì)微以達(dá)到對(duì)軟件相應(yīng)設(shè)計(jì)較差的代碼進(jìn)行改進(jìn)的目的。如今有一些軟件性能分析工具如linux的perf,以及C語言庫頭文件
實(shí)際上,實(shí)際系統(tǒng)中很難有完全精確的工具來對(duì)應(yīng)用程序的性能進(jìn)行不間斷的精確追蹤。這樣的精確追蹤。而計(jì)算機(jī)體系結(jié)構(gòu)仿真器是一個(gè)很好的解決方案。
計(jì)算機(jī)體系結(jié)構(gòu)仿真器主要是用來在系統(tǒng)層面探究和優(yōu)化計(jì)算機(jī)體系結(jié)構(gòu)參數(shù)設(shè)計(jì)的工具。通常而言,它們?cè)敿?xì)建模了某一計(jì)算機(jī)體系結(jié)構(gòu)內(nèi)部部件,諸如CPU執(zhí)行部件、cache等。軟件通過編譯可以在仿真工具上進(jìn)行運(yùn)行,運(yùn)行之后仿真器給出運(yùn)行結(jié)果統(tǒng)計(jì),從而驗(yàn)證軟件在某一組體系結(jié)構(gòu)參數(shù)(通常包括cache相聯(lián)性、內(nèi)存讀寫端口數(shù)等)的性能。本文利用SimpleScalar(SS)為基礎(chǔ)來開發(fā)MIPS架構(gòu)軟件性能探究工具。
SS是由Todd Austin開發(fā)的一個(gè)用于模擬計(jì)算機(jī)體積結(jié)構(gòu)諸如計(jì)算單元、緩存與內(nèi)存系統(tǒng)、分支猜測(cè)等部件在內(nèi)的開源仿真器。它本身攜帶了幾個(gè)處理器模型,仿真速度從快到慢,精度從低到高依次有sim-fast、simsafe、sim-prof i le、以及sim-outorder等。本文以sim-outorder作為依托,因?yàn)槠淠M程度最詳細(xì),囊括了整數(shù)、浮點(diǎn)寄存器、2級(jí)可配置cache、哈佛架構(gòu)并且擁有亂序執(zhí)行部件、預(yù)測(cè)執(zhí)行部件等現(xiàn)代處理器常見架構(gòu)。流水線方面,它詳細(xì)模擬了MIPS諸如取指、譯碼、執(zhí)行、訪存和回寫在內(nèi)的5級(jí)流水。
對(duì)于sim-outorder來講,SS以ruu_fetch()、ruu_dispatch()、ruu_commit()等幾個(gè)關(guān)鍵函數(shù)實(shí)現(xiàn)5級(jí)流水。在指令解碼方面,machine.def文件以宏定義的方式匯集了每個(gè)指令的指令名稱、指令碼、執(zhí)行方式、涉及功能部件等信息。
可執(zhí)行文件的格式標(biāo)識(shí)了可執(zhí)行文件的類型,不同的語言以及不同的執(zhí)行環(huán)境一般會(huì)產(chǎn)生不同類型的可執(zhí)行文件。如Linux平臺(tái)下可執(zhí)行文件格式主要有兩種:ELF和COFF。前者是現(xiàn)今Linux平臺(tái)下最為流行的可執(zhí)行文件格式,通常由GCC編譯的可執(zhí)行文件,其格式就是ELF。系統(tǒng)通常系統(tǒng)根據(jù)文件頭頭幾個(gè)字節(jié)來區(qū)分兩者的不同。而ECOFF格式是應(yīng)用于MIPS的可執(zhí)行文件格式。SS所應(yīng)用的是一種和ECOFF兼容的可執(zhí)行文件格式。
C語言是高級(jí)語言,通常情況下,每句C語言最終都被編譯為不止一句匯編語言。要完成C每行代碼和程序計(jì)數(shù)器(PC)的對(duì)應(yīng),首先就要完成C語言和匯編語言的對(duì)應(yīng)。
SS支持的是ECOFF格式的可執(zhí)行為文件,因此要下載其自己的binutils工具鏈來完成??梢栽诰幾g應(yīng)用程序時(shí)加上-g選項(xiàng)來進(jìn)行編譯。在編譯之后,利用objdump命令對(duì).o文件進(jìn)行處理,并加入--disassemble選項(xiàng)進(jìn)行反匯編,-l進(jìn)行行數(shù)顯示,--source進(jìn)行源代碼顯示。將產(chǎn)生的文件導(dǎo)入新的文件,這個(gè)文件就記錄了C代碼行號(hào)和匯編代碼的對(duì)應(yīng)關(guān)系。由于文件顯示信息過多,利用額外的程序?qū)υ撐募M(jìn)行正則匹配處理,之拿出行號(hào)和匯
編操作碼的對(duì)應(yīng)即可??紤]到后面的需要,只需要提取出來匯編指令操作碼即可。
SS的指令由64位構(gòu)成。前32位是操作碼,后32位是操作數(shù)。分別由8個(gè)16進(jìn)制數(shù)表示。ECOFF將可執(zhí)行文件分為.text、.rdata、.data、.sdata、.sbss和 .bss六個(gè)段。其中 .text段表示代碼段;.rdata表示只讀的數(shù)據(jù)段;.data段表示已被初始化的可讀寫數(shù)據(jù)段;.sdata表示;.sbss表示;.bss表示未初始化的數(shù)據(jù)段。
SS在加載可執(zhí)行文件的時(shí)候。首先會(huì)讀取可執(zhí)行文件的文件頭信息,里面涵蓋了7個(gè)信息,其中包含了魔數(shù)(f_magic)、段的個(gè)數(shù)(f_cscns)、文件建立時(shí)間(f_timdat)、符號(hào)表相對(duì)于文件的偏移量(f_symptr)、符號(hào)表?xiàng)l目個(gè)數(shù)(f_nsyms)、可選頭部長(zhǎng)度(f_opthdr)以及文件標(biāo)志(f_flags)。
除此之外,還有可選文件頭以及各個(gè)段的頭。每個(gè)段的頭所涵蓋的10個(gè)信息有:
段名稱(s_name);段物理地址(s_paddr);段虛擬地址(s_vaddr);段大小(s_size);段數(shù)據(jù)相對(duì)于文件的偏移量(s_scnptr);重定位信息偏移量(s_relptr);行信息偏移量(s_lnnptr);重定為條目數(shù)(s_nreloc);行信息條目數(shù)(s_nlnno);標(biāo)志(s_flags)。
要拿到匯編操作碼和PC指針的對(duì)應(yīng)關(guān)系,需要分析TEXT段的內(nèi)容。由于SS是以s_vaddr為基礎(chǔ)將代碼段整體放入仿真器內(nèi)存的,因此首先根據(jù)s_flags定位到TEXT段,然后在另一個(gè)文件中記錄出每8個(gè)字節(jié)提取前4個(gè)字節(jié)作為匯編操作碼,以及與此相對(duì)應(yīng)的PC值(即每個(gè)指令對(duì)應(yīng)的s_vaddr的值)。這樣可以得到操作碼和PC指針的對(duì)應(yīng)關(guān)系文件。
在得到C代碼行數(shù)和匯編操作碼對(duì)應(yīng)的關(guān)系文件以及匯編操作碼和PC指針的對(duì)應(yīng)關(guān)系文件后,便可以得到C語言行數(shù)和PC指針的對(duì)應(yīng)關(guān)系。這樣的記錄方式是對(duì)可執(zhí)行文件和執(zhí)行環(huán)境沒有侵入的,即沒有在可執(zhí)行文件中加入任何的記錄標(biāo)志,同時(shí)也沒有對(duì)cache進(jìn)行數(shù)據(jù)污染。
SS自帶有執(zhí)行過程各部件訪問統(tǒng)計(jì),但是沒有每周期的數(shù)據(jù),為了更好地分析可執(zhí)行文件的執(zhí)行過程,可以額外加入每周期的處理器各部件訪問統(tǒng)計(jì)。在每周期開始時(shí),將統(tǒng)計(jì)變量設(shè)為初始值,然后在執(zhí)行過程中在程序不同地方進(jìn)行每個(gè)統(tǒng)計(jì)變量的加操作,在一周期執(zhí)行完畢后,將結(jié)果記錄,同時(shí)再將統(tǒng)計(jì)變量設(shè)為初始值,以便下個(gè)周期進(jìn)行統(tǒng)計(jì)。
在執(zhí)行的每個(gè)周期都進(jìn)行統(tǒng)計(jì)和記錄,這樣就形成了PC和統(tǒng)計(jì)量的對(duì)應(yīng)關(guān)系文件。
由于在此之前提取了每周期C語言行數(shù)和PC指針的對(duì)應(yīng)關(guān)系文件以及每周期PC指針和該周期處理器各部件訪問統(tǒng)計(jì),因此可以最終得到記錄每周期C語言代碼和該周期處理器各部件訪問統(tǒng)計(jì)的文件。將此文件在MATLAB等工具中進(jìn)行可視化處理,便可以直觀分析軟件執(zhí)行過程中每行C語言代碼所造成的各部件訪問情況,從而達(dá)到指導(dǎo)軟件優(yōu)化的目的。
由于現(xiàn)階段程序性能分析工具會(huì)侵入目標(biāo)程序的自身或者執(zhí)行環(huán)境,不能做到精確分析軟件自身的問題。為了給目標(biāo)分析程序提供一個(gè)非侵入式的純凈執(zhí)行環(huán)境以便更好地分析程序的執(zhí)行性能和瓶頸,本文以SimpleScalar仿真器為基礎(chǔ),實(shí)現(xiàn)了一個(gè)可以與匯編、C程序每執(zhí)行周期嚴(yán)格對(duì)應(yīng)的應(yīng)用程序性能分析工具。本文也提出了一個(gè)較好的方法,即利用原本用來進(jìn)行處理器體系結(jié)構(gòu)探索的仿真工具來進(jìn)行目標(biāo)指令集和架構(gòu)的軟件性能探索和研究。如果有其它指令集或架構(gòu)的周期精確體系結(jié)構(gòu)仿真器,利用此方法,依然可以探索該平臺(tái)下的軟件性能。
參考文獻(xiàn)
[1]徐恒陽,安虹,劉玉,周偉.Perf在龍芯2F上的設(shè)計(jì)與實(shí)現(xiàn)[J].計(jì)算機(jī)工程,2011,19(37):236-238.
[2]SimpleScalar Architectural Research Tool Set,version 3.0.www.simplescalar.com.
[3]俞甲子,石凡,潘愛民.程序員的自我修養(yǎng)——鏈接、裝載與庫[M].電子工業(yè)出版社,2009.