孫衛(wèi)真,孫 星,向 勇
(1.首都師范大學(xué) 信息工程學(xué)院,北京 100048;2.清華大學(xué) 計(jì)算機(jī)科學(xué)與技術(shù)系,北京 100084)
在分析復(fù)雜結(jié)構(gòu)軟件或操作系統(tǒng)內(nèi)核時(shí),研究者會(huì)關(guān)注各模塊及函數(shù)之間的關(guān)系,借助源碼分析工具可以減少人工分辨模塊關(guān)系。傳統(tǒng)分析工具如LXR[1]、Kythe[2]通過檢索源碼,建立索引關(guān)系,以標(biāo)記和鏈接的方式輔助分析。文獻(xiàn)[3]靜態(tài)數(shù)據(jù)獲取使用基于寄存器傳送語言方式,讀取內(nèi)核編譯中間結(jié)果,形成更準(zhǔn)確的調(diào)用關(guān)系。為更好表現(xiàn)模塊及函數(shù)間的調(diào)用關(guān)系,有研究和工具運(yùn)用流程圖或有向圖[4]等方式展現(xiàn)。隨著Web技術(shù)的廣泛應(yīng)用與在線工具的出現(xiàn),用戶能夠在線進(jìn)行源碼分析工作,減少研究者本地部署的操作,文獻(xiàn)[5]使用數(shù)據(jù)庫存儲(chǔ)調(diào)用數(shù)據(jù),Web服務(wù)器讀取數(shù)據(jù)并渲染SVG格式的函數(shù)調(diào)用圖,通過靜態(tài)頁面展現(xiàn)。但服務(wù)器處理和渲染過程計(jì)算量大,傳輸數(shù)據(jù)存在大量冗余,導(dǎo)致等待時(shí)間過長。因此提高數(shù)據(jù)處理和渲染速度,減小傳輸數(shù)據(jù)量,能夠提高函數(shù)調(diào)用圖的生成速度。
本文工作概括如下:
(1)使用DBCG-RTL(date based call graph tool based on RTL)數(shù)據(jù)獲取方法,更新運(yùn)行環(huán)境,生成新版本內(nèi)核調(diào)用數(shù)據(jù),存儲(chǔ)在MySQL數(shù)據(jù)庫中,用于服務(wù)器數(shù)據(jù)獲??;
(2)基于Node.js使用egg.js框架搭建API服務(wù)器,使用異步方式處理并返回客戶端所需數(shù)據(jù);
(3)基于Vue.js搭建頁面,使用Antv-G6可視化庫,實(shí)現(xiàn)在線函數(shù)調(diào)用圖模塊,動(dòng)態(tài)加載圖數(shù)據(jù)并更新調(diào)用圖;
(4)使用Linux-4.15.18 x64內(nèi)核數(shù)據(jù),對(duì)DBCG-RTL與FRCG工具進(jìn)行測(cè)試,結(jié)果表明FRCG工具生成50節(jié)點(diǎn)以下函數(shù)調(diào)用圖時(shí),平均減少60.09%等待時(shí)間,平均減少92.24%傳輸數(shù)據(jù)。
在內(nèi)核源碼的分析過程中,由于Linux源碼版本多、文件和函數(shù)間交叉引用數(shù)量巨大。傳統(tǒng)工具LXR[1]、Kythe[2]等通過檢索源碼,識(shí)別函數(shù)定義與調(diào)用的文件位置進(jìn)行記錄,以鏈接方式展示調(diào)用關(guān)系,但大型項(xiàng)目或內(nèi)核中存在大量同名函數(shù),掃描靜態(tài)源碼,無法準(zhǔn)確匹配調(diào)用函數(shù),只能提供索引列表。
借助可視化工具,能夠更直觀查看函數(shù)調(diào)用關(guān)系。毛等[3]開發(fā)了DCG-RTL工具,將內(nèi)核二次編譯讀取調(diào)用關(guān)系數(shù)據(jù)與模擬器動(dòng)態(tài)監(jiān)控?cái)?shù)據(jù)結(jié)合,構(gòu)建內(nèi)核調(diào)用關(guān)系圖,但其采用文件形式存儲(chǔ),在渲染過程中,查找速度較慢。在此基礎(chǔ)上,賈等[5]開發(fā)了DBCG-RTL工具,使用數(shù)據(jù)庫存儲(chǔ)函數(shù)調(diào)用關(guān)系,提高查詢速度,并將函數(shù)調(diào)用圖和函數(shù)調(diào)用列表等模塊集成在LXR的Web服務(wù)器中。由于LXR為服務(wù)器渲染生成頁面,數(shù)據(jù)讀取、處理與調(diào)用圖、頁面的渲染都在服務(wù)器上進(jìn)行,造成計(jì)算量大,等待時(shí)間長等問題。同時(shí)頁面渲染和數(shù)據(jù)處理代碼耦合在一起,加大了維護(hù)和拓展的難度,造成工具難以移植和更新。
針對(duì)Web服務(wù)器處理時(shí)間長的問題,有研究人員對(duì)不同服務(wù)器進(jìn)行對(duì)比,Chitra等[6]對(duì)比Node.js和傳統(tǒng)Web服務(wù)器性能,得出Node.js服務(wù)器具有輕巧高效的特點(diǎn);Chaniotis等[7]對(duì)Apache,PHP,Node.js和Nginx進(jìn)行性能分析,指出Node.js在內(nèi)存和CPU的利用率明顯優(yōu)于Apache 和PHP,并提出將Nginx與Node.js結(jié)合的框架,用于開發(fā)具有模塊化、實(shí)時(shí)信息通訊和拓展性強(qiáng)等需求的Web應(yīng)用;有研究人員基于Node.js實(shí)現(xiàn)前后端分離的平臺(tái)系統(tǒng),朱等[8]使用基于Node.js的Koa后端框架和Vue.js前端框架,對(duì)物流信息管理系統(tǒng)進(jìn)行研究與實(shí)現(xiàn),通過Node.js非阻塞I/O、事件驅(qū)動(dòng)等特性,實(shí)現(xiàn)較快的頁面加載時(shí)間。Eric Wohlgethan[9]對(duì)Angular、React、Vue.js前端框架進(jìn)行了分析,總結(jié)Vue.js用于開發(fā)單頁面應(yīng)用,學(xué)習(xí)成本低,同時(shí)框架實(shí)現(xiàn)數(shù)據(jù)和視圖的雙向綁定,視圖的更新由框架提供,開發(fā)過程只需要專注于數(shù)據(jù)的處理。
對(duì)于數(shù)據(jù)可視化,DBCG-RTL工具[5]處理調(diào)用圖數(shù)據(jù)后,使用Graphviz工具渲染生成SVG圖,該工具語法簡單,能夠自動(dòng)布局節(jié)點(diǎn)分布。但腳本進(jìn)行渲染和布局的速度慢,同時(shí)會(huì)增加服務(wù)器計(jì)算壓力;生成SVG中包含渲染后屬性,增加傳輸?shù)臄?shù)據(jù)量。基于前端可視化實(shí)現(xiàn)主要有:Cytoscape.js[10]是一個(gè)開源關(guān)系圖可視化庫,提供多種布局方式,功能完善,但其視圖操作基于選擇器實(shí)現(xiàn),不適用在Vue模塊化的前端框架中;Echarts[11,12]為百度團(tuán)隊(duì)開發(fā)的前端圖庫,支持基礎(chǔ)圖表,也支持樹圖、關(guān)系圖等,具有良好的可視化效果,但其對(duì)于關(guān)系圖的支持較為不足,需要自行實(shí)現(xiàn)相關(guān)功能;冉等[13]基于Echarts模塊,對(duì)專利數(shù)據(jù)進(jìn)行可視化處理;AntV[14]作為阿里旗下螞蟻金服可視化解決方案,將不同類別圖進(jìn)行了不同的劃分,G2可視化、G6圖可視化、F2移動(dòng)可視化、L7地理空間可視化。其中G6對(duì)圖的數(shù)據(jù)關(guān)系,具有完善的功能支持,能良好兼容Vue模塊化前端框架,文檔豐富,便于二次開發(fā);文獻(xiàn)[15]使用G2圖庫開發(fā)了LnCompare,可以對(duì)長非編碼RNA數(shù)據(jù)進(jìn)行在線可視化分析。
本文目的是提高分析工具調(diào)用圖的生成速度,使用前后端分離方式,將數(shù)據(jù)處理和可視化獨(dú)立到前后端完成;轉(zhuǎn)移服務(wù)器渲染調(diào)用圖的計(jì)算量,從而提高數(shù)據(jù)處理速度,減小前后端傳輸數(shù)據(jù)量;前端頁面使用Vue框架降低頁面框架內(nèi)容實(shí)現(xiàn)難度,調(diào)用圖使用AntV-G6實(shí)現(xiàn)調(diào)用數(shù)據(jù)的可視化,動(dòng)態(tài)渲染調(diào)用圖,解決DBCG-RTL[5]調(diào)用圖渲染時(shí)間過長的問題,并提高調(diào)用圖的靈活性。同時(shí)前后端統(tǒng)一開發(fā)環(huán)境,降低工具拓展和維護(hù)難度。
基于前后端分離思想,F(xiàn)RCG函數(shù)調(diào)用圖工具主要由Node.js搭建的API服務(wù)器和Vue.js搭建的單頁面應(yīng)用兩個(gè)部分組成,通過docker容器進(jìn)行部署,如圖1所示,框架分為MySQL、Node和Nginx這3個(gè)容器。Nginx容器提供頁面文件Web服務(wù)和對(duì)API接口的反向代理,Node容器提供處理API接口請(qǐng)求的服務(wù)器,MySQL容器作為數(shù)據(jù)存儲(chǔ)。
(1)MySQL容器:使用DBCG-RTL[5]方法,生成Linux 4.15版本之后內(nèi)核調(diào)用數(shù)據(jù),存儲(chǔ)在MySQL數(shù)據(jù)庫中。Node.js服務(wù)器從中查詢所需要的內(nèi)核數(shù)據(jù)。
(2)Node容器:基于Node.js的egg.js框架搭建API服務(wù)器,使用異步方式處理請(qǐng)求內(nèi)容和查詢數(shù)據(jù)庫,并將數(shù)據(jù)轉(zhuǎn)換成對(duì)應(yīng)格式,作為請(qǐng)求的返回?cái)?shù)據(jù)。為前端頁面提供數(shù)據(jù)接口。
(3)Nginx容器:基于Vue.js搭建的單頁面應(yīng)用通過打包形成靜態(tài)頁面文件,使用Nginx部署頁面資源。用戶使用瀏覽器訪問,獲取頁面文件到本地瀏覽器中渲染執(zhí)行,頁面中調(diào)用圖、調(diào)用表等模塊使用Http請(qǐng)求服務(wù)器對(duì)應(yīng)API接口獲取數(shù)據(jù),得到數(shù)據(jù)后,頁面腳本進(jìn)行可視化渲染。作為FRCG工具的主要展現(xiàn)方式。
圖1 FRCG總體框架
圖2 服務(wù)器框架
Node.js服務(wù)器框架,主要分為路由、控制器、服務(wù)、插件這4部分組成,如圖2所示。
路由(Router)中定義了接口URL對(duì)應(yīng)的控制器模塊,根據(jù)獲取數(shù)據(jù)的不同設(shè)計(jì)為3種接口,分別是函數(shù)調(diào)用圖接口/graphs用于獲取調(diào)用圖數(shù)據(jù);函數(shù)調(diào)用表接口/functions用于獲取調(diào)用表數(shù)據(jù);配置信息接口/options用于頁面獲取配置模塊所需數(shù)據(jù),實(shí)現(xiàn)頁面登錄和菜單列表功能。
控制器(Controller)負(fù)責(zé)解析路由分發(fā)請(qǐng)求中包含的參數(shù),調(diào)用驗(yàn)證插件進(jìn)行合法性驗(yàn)證,提取請(qǐng)求中的數(shù)據(jù)作為參數(shù),調(diào)用對(duì)應(yīng)的服務(wù)模塊函數(shù)進(jìn)行數(shù)據(jù)處理,返回響應(yīng)數(shù)據(jù)。
服務(wù)(Service)負(fù)責(zé)處理數(shù)據(jù),簡化控制器代碼,獨(dú)立數(shù)據(jù)的處理函數(shù)。模塊根據(jù)調(diào)用參數(shù),進(jìn)行數(shù)據(jù)查詢和特定規(guī)則的計(jì)算,生成所需數(shù)據(jù),根據(jù)需求寫入數(shù)據(jù)庫并返回給控制器。
插件(Plugin)主要為官方或三方實(shí)現(xiàn)的功能模塊,如安全驗(yàn)證、數(shù)據(jù)驗(yàn)證、MySQL訪問等。
根據(jù)頁面模塊所需數(shù)據(jù)為調(diào)用圖的節(jié)點(diǎn)及邊數(shù)據(jù)和調(diào)用表的詳細(xì)數(shù)據(jù),將服務(wù)器API接口設(shè)計(jì)為獲取調(diào)用圖數(shù)據(jù)的API接口和獲取調(diào)用表數(shù)據(jù)的API接口。
3.1.1 調(diào)用圖API設(shè)計(jì)
頁面調(diào)用圖所需數(shù)據(jù)主要為:獲取對(duì)應(yīng)內(nèi)核版本、編譯環(huán)境下,兩個(gè)路徑間的調(diào)用關(guān)系圖數(shù)據(jù);獲取調(diào)用圖中某節(jié)點(diǎn)下一級(jí)節(jié)點(diǎn)與當(dāng)前圖中節(jié)點(diǎn)調(diào)用關(guān)系的圖數(shù)據(jù);上傳調(diào)用圖數(shù)據(jù),存儲(chǔ)并返回分享id;獲取分享id對(duì)應(yīng)的調(diào)用圖數(shù)據(jù)。
根據(jù)頁面需求調(diào)用圖API需要實(shí)現(xiàn):依據(jù)請(qǐng)求參數(shù)返回調(diào)用圖數(shù)據(jù)、存儲(chǔ)請(qǐng)求中上傳的調(diào)用圖數(shù)據(jù)并返回存儲(chǔ)id、獲取對(duì)應(yīng)id的調(diào)用圖數(shù)據(jù)。具體接口定義見表1。
表1 調(diào)用圖API定義
根據(jù)生成內(nèi)核函數(shù)調(diào)用圖的不同,需求的參數(shù)列表見表2。請(qǐng)求中包含內(nèi)核版本、平臺(tái)、生成調(diào)用圖的源路徑、目標(biāo)路徑的必須參數(shù),根據(jù)調(diào)用圖的功能不同,請(qǐng)求中可以增加配置參數(shù):用于獲取不顯示同級(jí)路徑調(diào)用圖的per參數(shù)、用于獲取展開節(jié)點(diǎn)數(shù)據(jù)的id、expand和expanded參數(shù)。
表2 調(diào)用圖API參數(shù)
服務(wù)器讀取參數(shù)后,根據(jù)配置進(jìn)行數(shù)據(jù)處理,以JSON格式返回,返回?cái)?shù)據(jù)中,包含圖id、節(jié)點(diǎn)數(shù)據(jù)、邊數(shù)據(jù)等。以請(qǐng)求Linux-4.15.18內(nèi)核fs和mm模塊返回?cái)?shù)據(jù)為例,部分內(nèi)容如代碼1所示。
代碼1:調(diào)用圖返回?cái)?shù)據(jù)
params: {
id: "4-15-18 x86_64 /fs /mm"
data: {n
nodes:[
{id: "/mm/gup.c", type: 0},
…
],
edges:[
{source: "/mm/gup.c", target: "/fs", sourceWeight: 8, type: 2},
…
]
}
}
3.1.2 調(diào)用表API設(shè)計(jì)
頁面中調(diào)用表需要內(nèi)核版本、編譯環(huán)境下,兩個(gè)路徑間的調(diào)用數(shù)據(jù),同時(shí)為了實(shí)現(xiàn)源碼跳轉(zhuǎn)功能,會(huì)獲取某個(gè)函數(shù)的詳細(xì)數(shù)據(jù)。調(diào)用表API功能簡單,主要為獲取路徑間調(diào)用表和獲取函數(shù)定義,具體定義見表3。
表3 調(diào)用表API定義
請(qǐng)求中需求參數(shù)為內(nèi)核版本、平臺(tái)、源路徑、目標(biāo)路徑,見表4。請(qǐng)求返回?cái)?shù)據(jù)中包含函數(shù)調(diào)用的數(shù)據(jù):源函數(shù)名、源函數(shù)所在文件、行號(hào)、調(diào)用行號(hào)、目標(biāo)函數(shù)名、目標(biāo)函數(shù)所在文件、行號(hào)、調(diào)用次數(shù)等。
表4 調(diào)用表API參數(shù)
服務(wù)器中請(qǐng)求處理過程相似,流程為路由分配,控制器調(diào)用服務(wù)生成數(shù)據(jù)并返回響應(yīng)數(shù)據(jù)。不同模塊控制器會(huì)根據(jù)功能需求對(duì)數(shù)據(jù)進(jìn)行驗(yàn)證,調(diào)用對(duì)應(yīng)服務(wù)進(jìn)行處理,通過不同的處理方式,生成不同請(qǐng)求所需的數(shù)據(jù)。
3.2.1 調(diào)用圖數(shù)據(jù)處理實(shí)現(xiàn)
客戶端請(qǐng)求經(jīng)路由分配到使用GET方法的/graphs接口后,處理過程如下:
(1)控制器處理請(qǐng)求:控制器驗(yàn)證請(qǐng)求數(shù)據(jù),驗(yàn)證通過后,控制器提取請(qǐng)求數(shù)據(jù)作為參數(shù),調(diào)用對(duì)應(yīng)服務(wù)進(jìn)行處理;
(2)服務(wù)模塊讀取調(diào)用參數(shù):獲取參數(shù)中的內(nèi)核版本、平臺(tái)和路徑等數(shù)據(jù),并讀取非必須的配置項(xiàng),用于區(qū)分所需函數(shù)調(diào)用圖功能,如:存在expand屬性則此請(qǐng)求為對(duì)現(xiàn)有函數(shù)調(diào)用圖節(jié)點(diǎn)展開數(shù)據(jù)的請(qǐng)求,存在per屬性為false則此請(qǐng)求為不需要同級(jí)節(jié)點(diǎn)數(shù)據(jù)的內(nèi)部函數(shù)調(diào)用圖。對(duì)于無額外配置項(xiàng)的參數(shù),默認(rèn)為獲取對(duì)應(yīng)內(nèi)核版本下兩路徑之間的函數(shù)調(diào)用圖;
(3)初始化配置數(shù)據(jù):使用參數(shù)中的內(nèi)核版本等數(shù)據(jù),初始化調(diào)用圖配置數(shù)據(jù),如查詢數(shù)據(jù)庫的表名、圖id等;
(4)檢索歷史數(shù)據(jù)庫:根據(jù)初始化后的圖id,檢索歷史數(shù)據(jù)中是否存在該圖數(shù)據(jù),若存在歷史數(shù)據(jù),將數(shù)據(jù)返回給控制器。若無歷史數(shù)據(jù),則通過異步方式查詢數(shù)據(jù)庫生成調(diào)用圖數(shù)據(jù),將生成數(shù)據(jù)返回給控制器,并寫入歷史數(shù)據(jù)庫;
(5)返回?cái)?shù)據(jù):控制器得到服務(wù)文件返回?cái)?shù)據(jù),作為請(qǐng)求數(shù)據(jù)返回給客戶端,請(qǐng)求處理完成。
過程優(yōu)化:
DBCG-RTL中計(jì)算調(diào)用圖數(shù)據(jù)主要過程為:
(1)查詢靜態(tài)函數(shù)定義表(FDLIST),獲取源路徑和目標(biāo)路徑的下級(jí)路徑。若輸入為路徑,下一級(jí)則為子路徑DBCG-RTL或文件,若輸入為文件,下一級(jí)為文件內(nèi)函數(shù)名。同時(shí)使用遞歸方式逐級(jí)查找同級(jí)和上級(jí)路徑。將查找到的路徑,所屬類別轉(zhuǎn)換成節(jié)點(diǎn)集合;
(2)得到節(jié)點(diǎn)的集合后,依次遍歷節(jié)點(diǎn)集合中不同的兩個(gè)節(jié)點(diǎn),查詢靜態(tài)外部引用列表(SOLIST)獲取兩個(gè)節(jié)點(diǎn)間的調(diào)用次數(shù);
(3)函數(shù)調(diào)用圖所需數(shù)據(jù)查詢完畢,需要對(duì)數(shù)據(jù)格式進(jìn)行處理,生成符合Graphviz需求格式的數(shù)據(jù);
(4)針對(duì)調(diào)用圖計(jì)算過程中,對(duì)調(diào)用關(guān)系的大量查詢,本文采用異步處理方式提高處理速度;同時(shí)前后端統(tǒng)一使用JSON數(shù)據(jù)傳輸,減少傳輸圖數(shù)據(jù)的大小。
提高計(jì)算速度:
查詢節(jié)點(diǎn)間的調(diào)用關(guān)系可以看作查詢N節(jié)點(diǎn)的有向圖,遍歷不同節(jié)點(diǎn)間的調(diào)用關(guān)系需要進(jìn)行復(fù)雜度為O(N2)的查詢。DBCG-RTL通過Ruby腳本線性執(zhí)行SQL語句直接查詢MySQL數(shù)據(jù),本文通過egg-mysql插件代理訪問,線性執(zhí)行相同的查詢操作,處理時(shí)間比Ruby腳本慢。
基于Node.js的事件循環(huán)和非阻塞I/O機(jī)制:對(duì)于連續(xù)的查詢操作,Node.js將其視為一組事件隊(duì)列,依次執(zhí)行其中的查詢操作。在發(fā)起查詢數(shù)據(jù)庫操作后,不會(huì)阻塞查詢的繼續(xù)執(zhí)行,而是將返回?cái)?shù)據(jù)的操作放在回調(diào)函數(shù)中,并繼續(xù)下一次查詢。當(dāng)數(shù)據(jù)庫查詢操作返回結(jié)果后,將處理數(shù)據(jù)的回調(diào)函數(shù)插入事件隊(duì)列,等待執(zhí)行。Node.js會(huì)不斷檢查當(dāng)前事件隊(duì)列,并以一定順序去執(zhí)行各類回調(diào)函數(shù)。
而在處理請(qǐng)求所需的節(jié)點(diǎn)調(diào)用數(shù)據(jù)過程中,通過異步方式發(fā)起查詢,在回調(diào)函數(shù)還未執(zhí)行時(shí),請(qǐng)求處理函數(shù)就已經(jīng)執(zhí)行完成并返回,造成返回?cái)?shù)據(jù)列表為空的情況。為解決返回?cái)?shù)據(jù)為空的問題,本文構(gòu)造Promise對(duì)象列表,每個(gè)Promise對(duì)象為查詢數(shù)據(jù)庫中兩節(jié)點(diǎn)間的調(diào)用頻度函數(shù),數(shù)據(jù)返回后通過回調(diào)函數(shù)將調(diào)用數(shù)據(jù)添加到邊數(shù)據(jù)列表中。執(zhí)行Promise.all(list)函數(shù),實(shí)現(xiàn)以非阻塞的方式執(zhí)行對(duì)象列表中全部查詢,以阻塞的方式執(zhí)行回調(diào)函數(shù),得到全部節(jié)點(diǎn)間的調(diào)用數(shù)據(jù)。同步執(zhí)行和異步讀取結(jié)合,提高數(shù)據(jù)獲取速度。
減小數(shù)據(jù)大小:
DBCG-RTL生成的SVG圖,節(jié)點(diǎn)和邊存在大量未進(jìn)行優(yōu)化的冗余內(nèi)容和渲染屬性數(shù)據(jù),導(dǎo)致傳輸數(shù)據(jù)較大;Node.js服務(wù)器提供處理后的圖數(shù)據(jù),只包含節(jié)點(diǎn)和邊的基礎(chǔ)屬性數(shù)據(jù),如節(jié)點(diǎn)id、節(jié)點(diǎn)類型、邊類型、邊源和目標(biāo)等數(shù)據(jù),能夠大幅度減少傳輸數(shù)據(jù)。如圖3所示:本文分離頁面文件和數(shù)據(jù)的傳輸,減小了每次請(qǐng)求所需的頁面文件,調(diào)用圖數(shù)據(jù)由頁面動(dòng)態(tài)請(qǐng)求;前后端使用JSON格式傳輸數(shù)據(jù),減小SVG中的渲染數(shù)據(jù)和XML標(biāo)簽結(jié)構(gòu)數(shù)據(jù),降低傳輸數(shù)據(jù)大小,提升傳輸速度。
圖3 傳輸內(nèi)容對(duì)比
3.2.2 調(diào)用表數(shù)據(jù)處理實(shí)現(xiàn)
Get/functions接口數(shù)據(jù)處理流程與調(diào)用圖處理流程相似,具體差異在數(shù)據(jù)的查詢和處理部分。
調(diào)用表數(shù)據(jù)查詢過程與DBCG-RTL方法相似,查詢SOLIST表得到兩路徑之間存在調(diào)用關(guān)系的函數(shù)、所在文件和調(diào)用次數(shù);根據(jù)函數(shù)名和所在文件查詢FDLIST表,得到函數(shù)在數(shù)據(jù)庫中的id和文件內(nèi)起始行號(hào);根據(jù)源函數(shù)id和被調(diào)用函數(shù)id查詢SLIST表得到全部調(diào)用行號(hào)。
過程優(yōu)化:
計(jì)算調(diào)用表數(shù)據(jù)優(yōu)化與調(diào)用圖優(yōu)化相似,使用異步處理大量查詢。處理流程中查詢SOLIST可以得到調(diào)用關(guān)系數(shù)據(jù),數(shù)據(jù)中缺少函數(shù)定義數(shù)據(jù)和調(diào)用行號(hào)數(shù)據(jù);函數(shù)定義數(shù)據(jù),通過構(gòu)造Promise對(duì)象實(shí)現(xiàn)異步查詢FDLIST表,得到函數(shù)在數(shù)據(jù)庫中的id和文件內(nèi)起始行號(hào);調(diào)用行號(hào)數(shù)據(jù),通過構(gòu)造Promise對(duì)象實(shí)現(xiàn)異步查詢SLIST表得到全部調(diào)用行號(hào)。使用Promise.all()函數(shù)同步得到全部查詢結(jié)果。
前端頁面作為FRCG工具的主要展示途徑,提供了可交互的調(diào)用圖和詳細(xì)數(shù)據(jù)的調(diào)用表。同時(shí)提供自定義布局模塊,實(shí)現(xiàn)對(duì)調(diào)用圖和調(diào)用表模塊布局的自定義。頁面各部分框架如圖4所示,本文通過EventBus構(gòu)建事件總線,完成調(diào)用圖組件對(duì)其它組件的事件傳遞,實(shí)現(xiàn)調(diào)用圖的復(fù)雜交互功能。
圖4 頁面交互事件
調(diào)用圖頁面中,用戶通過選擇器組件修改頁面配置數(shù)據(jù)(config),此配置作為頁面子組件:調(diào)用圖組件和調(diào)用表組件的輸入?yún)?shù)。圖組件中用戶的操作,如點(diǎn)擊右鍵菜單執(zhí)行切換調(diào)用圖,會(huì)向頁面發(fā)布修改配置數(shù)據(jù)的事件,觸發(fā)頁面修改對(duì)應(yīng)配置數(shù)據(jù),調(diào)用圖組件會(huì)根據(jù)輸入配置參數(shù)的變化,更新圖數(shù)據(jù)重新渲染生成調(diào)用圖。
圖頁面的一組選擇器,供用戶配置圖所需的參數(shù):內(nèi)核版本、內(nèi)核平臺(tái)、源路徑、目標(biāo)路徑、僅顯示內(nèi)部節(jié)點(diǎn)、圖布局方式。內(nèi)核版本及平臺(tái)等數(shù)據(jù),在頁面初始化過程中,會(huì)向服務(wù)器請(qǐng)求獲取,用戶選擇版本內(nèi)核后,會(huì)動(dòng)態(tài)加載對(duì)應(yīng)內(nèi)核的路徑數(shù)據(jù)。這些數(shù)據(jù)存儲(chǔ)在內(nèi)存中,切換同一內(nèi)核版本調(diào)用圖時(shí),能夠直接獲取內(nèi)核版本數(shù)據(jù);切換不同內(nèi)核調(diào)用圖時(shí),當(dāng)選擇器選中后,會(huì)更新內(nèi)存中的內(nèi)核版本數(shù)據(jù)。
組件中選中的配置數(shù)據(jù),綁定到圖組件和表組件的輸入?yún)?shù),當(dāng)調(diào)用圖顯示時(shí),用戶通過選擇器組件更改配置數(shù)據(jù),會(huì)觸發(fā)調(diào)用圖的更新。
在頁面中引入Vue-grid-layout組件實(shí)現(xiàn)拖拽布局,將調(diào)用圖模塊和調(diào)用表模塊嵌套在布局組件中,并綁定布局組件大小變化事件到調(diào)用圖組件size傳入數(shù)據(jù)上,通過調(diào)用圖組件中監(jiān)控size變化,執(zhí)行調(diào)用圖的更新寬高函數(shù)。自定義布局可以改變調(diào)用圖和調(diào)用表大小和位置,默認(rèn)頁面布局為上下兩部分,用戶通過改變模塊尺寸,拖拽模塊等操作來實(shí)現(xiàn)左右或交換上下位置的布局。
圖組件接收頁面?zhèn)魅氲呐渲脭?shù)據(jù)(config),用戶通過選擇器選擇配置時(shí)會(huì)更新圖組件傳入的config,當(dāng)配置項(xiàng)完整后頁面才會(huì)顯示圖組件,避免由于配置數(shù)據(jù)不完整而造成請(qǐng)求調(diào)用圖數(shù)據(jù)失敗。
調(diào)用圖組件由:篩選開關(guān)組件、G6圖組件、右鍵菜單組件、彈窗組件組成。
(1)篩選開關(guān)組件:通過一組開關(guān)組件,綁定一組篩選配置數(shù)組,用于過濾圖中不同種類邊,輔助使用者找到分析的目標(biāo)節(jié)點(diǎn)和調(diào)用邊,提供分類有:源為非所選路徑節(jié)點(diǎn)、目標(biāo)為非所選路徑節(jié)點(diǎn)、源路徑節(jié)點(diǎn)到目標(biāo)路徑節(jié)點(diǎn)、目標(biāo)路徑節(jié)點(diǎn)到源路徑節(jié)點(diǎn)、源路徑節(jié)點(diǎn)到源路徑節(jié)點(diǎn)、目標(biāo)路徑節(jié)點(diǎn)到目標(biāo)路徑節(jié)點(diǎn)。開關(guān)組件綁定數(shù)據(jù)改邊時(shí),會(huì)對(duì)當(dāng)前調(diào)用圖中全部邊進(jìn)行遍歷,根據(jù)篩選配置數(shù)組,編輯邊的顯示屬性。同時(shí),當(dāng)調(diào)用圖更新時(shí),也需要對(duì)邊的顯示屬性進(jìn)行檢查;
(2)G6圖組件:作為調(diào)用圖組件的主體,用于顯示函數(shù)調(diào)用圖,還包含大量圖交互事件,如右鍵彈出對(duì)應(yīng)菜單;鼠標(biāo)覆蓋節(jié)點(diǎn)和邊進(jìn)行高亮相關(guān)元素;拖拽移動(dòng)圖和節(jié)點(diǎn);縮小放大調(diào)用圖等;
(3)右鍵菜單組件:作為切換和跳轉(zhuǎn)的主要途徑,如圖所示組件中包含大量傳遞給其它組件的事件,為統(tǒng)一事件傳遞方式,采用EventBus(事件總線)進(jìn)行傳遞,由組件根據(jù)用戶點(diǎn)擊菜單內(nèi)容,向總線中發(fā)布事件,其它組件訂閱相應(yīng)事件,執(zhí)行相應(yīng)操作;
(4)彈窗組件:用于顯示錯(cuò)誤信息及顯示分享圖的鏈接信息。
調(diào)用表組件接收頁面提供的config,其中包含內(nèi)核版本、平臺(tái)、源路徑、目標(biāo)路徑,當(dāng)配置項(xiàng)完整時(shí),使用element-ui中的表格組件進(jìn)行渲染,在組件聲明表格列,并配置列的屬性項(xiàng)如:列排序依據(jù)、列內(nèi)元素類型等。當(dāng)列內(nèi)元素為按鈕類型時(shí),需要在列中定義按鈕組件,并傳遞數(shù)據(jù)顯示,綁定函數(shù)實(shí)現(xiàn)點(diǎn)擊行號(hào)跳轉(zhuǎn)源碼頁面操作。
通過調(diào)用圖邊的右鍵菜單發(fā)出事件show function list、頁面補(bǔ)全調(diào)用表配置、渲染顯示調(diào)用表。
調(diào)用圖組件基于G6模塊實(shí)現(xiàn),通過定義初始化函數(shù),對(duì)調(diào)用圖的顯示和交互進(jìn)行定制和拓展,通過G6模塊提供的函數(shù),實(shí)現(xiàn)更新數(shù)據(jù)、渲染調(diào)用圖、保存當(dāng)前圖數(shù)據(jù)等功能。FRCG實(shí)現(xiàn)對(duì)圖數(shù)據(jù)的更新、添加和拷貝,調(diào)用圖的顯示、切換、局部更新和服務(wù)器備份等功能,對(duì)比DBCG-RTL通過靜態(tài)圖文件的方式展示調(diào)用圖,F(xiàn)RCG基于數(shù)據(jù)的操作具有更多靈活性,同時(shí)數(shù)據(jù)能夠進(jìn)行二次利用和分析,具有更多的拓展性。
4.5.1 調(diào)用圖實(shí)現(xiàn)
用戶通過選擇器組件配置完整后,圖組件進(jìn)行渲染顯示,生成調(diào)用圖過程如下:
(1)圖組件將輸入的配置參數(shù)進(jìn)行處理,提取并保存為內(nèi)部配置;
(2)初始化G6圖組件,綁定圖組件內(nèi)部響應(yīng)事件,如鼠標(biāo)覆蓋高亮、提示框彈出、右鍵菜單彈出與關(guān)閉等;
(3)根據(jù)當(dāng)前配置數(shù)據(jù),向服務(wù)器發(fā)起圖數(shù)據(jù)請(qǐng)求,得到返回?cái)?shù)據(jù)后,對(duì)數(shù)據(jù)進(jìn)行處理,根據(jù)節(jié)點(diǎn)id信息,增加節(jié)點(diǎn)label屬性,用于提示框顯示,根據(jù)節(jié)點(diǎn)和邊的type屬性,為節(jié)點(diǎn)和邊增加顯示顏色;
(4)將處理后的數(shù)據(jù)加載到G6圖組件中,調(diào)用組件render()函數(shù)渲染調(diào)用圖;
(5)模塊會(huì)監(jiān)控輸入配置參數(shù),當(dāng)屬性發(fā)生變化時(shí),根據(jù)配置參數(shù)獲取新的調(diào)用圖數(shù)據(jù),調(diào)用組件data()方法更新數(shù)據(jù),并使用render()方法重新渲染調(diào)用圖。
4.5.2 局部更新數(shù)據(jù)
將函數(shù)調(diào)用數(shù)據(jù)作為操作對(duì)象后,調(diào)用圖的更新能夠通過增加部分?jǐn)?shù)據(jù),達(dá)到增量更新的效果。在請(qǐng)求數(shù)據(jù)時(shí),配置非必須參數(shù):id、expand、expanded,用于獲取符合對(duì)應(yīng)圖中展開節(jié)點(diǎn)后的新增數(shù)據(jù)。頁面通過事件總線將更新函數(shù)綁定右鍵菜單中的節(jié)點(diǎn)展開按鈕,展開節(jié)點(diǎn)時(shí),調(diào)用圖組件會(huì)遍歷當(dāng)前圖中節(jié)點(diǎn)與邊,刪除被展開節(jié)點(diǎn)與相關(guān)聯(lián)的邊,以代碼2所示請(qǐng)求數(shù)據(jù)向服務(wù)器請(qǐng)求展開節(jié)點(diǎn)數(shù)據(jù):
代碼2:請(qǐng)求數(shù)據(jù)
params: {
version: "4-xx-xx",
source: "/xx",
target: "/xx",
id: "4-xx-xx /xx /xx",
espand: "/xx/xx"
}
得到請(qǐng)求返回的數(shù)據(jù),將數(shù)據(jù)和現(xiàn)有數(shù)據(jù)合并,使用合并后的數(shù)據(jù)重新渲染調(diào)用圖,實(shí)現(xiàn)增量更新展開節(jié)點(diǎn)。
需要注意的是,當(dāng)圖中存在多個(gè)展開節(jié)點(diǎn)時(shí),頁面會(huì)提示“存在多個(gè)展開節(jié)點(diǎn),展開節(jié)點(diǎn)之間的邊不會(huì)顯示”當(dāng)圖中展開節(jié)點(diǎn),達(dá)到3個(gè)時(shí),將會(huì)彈出錯(cuò)誤提示,并拒絕繼續(xù)加載新的展開節(jié)點(diǎn)。
4.5.3 分享調(diào)用圖
通過G6模塊graph.save()方法,可以保存當(dāng)前圖中的節(jié)點(diǎn)數(shù)據(jù),數(shù)據(jù)中包含節(jié)點(diǎn)坐標(biāo)等渲染后的圖數(shù)據(jù)。將此數(shù)據(jù)上傳到服務(wù)器,實(shí)現(xiàn)保存特定調(diào)用圖的目的。在調(diào)用圖中,通過右鍵彈出菜單選擇分享圖。點(diǎn)擊后,頁面將通過G6圖中g(shù)raph.save()函數(shù)獲取當(dāng)前圖中節(jié)點(diǎn)和邊的詳細(xì)數(shù)據(jù),對(duì)數(shù)據(jù)進(jìn)行過濾,只將當(dāng)前圖的必要數(shù)據(jù)上傳給服務(wù)器。服務(wù)器收到數(shù)據(jù)進(jìn)行存儲(chǔ),將圖的版本、源路徑和目標(biāo)路徑等標(biāo)志信息進(jìn)行MD5處理,得到哈希值作為數(shù)據(jù)的索引,返回給頁面此哈希數(shù)據(jù)。頁面補(bǔ)全URL路徑生成分享鏈接,并彈窗顯示分享鏈接。
在新的頁面中打開分享鏈接,頁面初始化過程中會(huì)根據(jù)URL中包含的哈希數(shù)據(jù),向服務(wù)器獲取分享頁面的配置和圖數(shù)據(jù)。獲取到數(shù)據(jù)后會(huì)先根據(jù)數(shù)據(jù)中的原有配置更新頁面和圖配置,將頁面得到圖數(shù)據(jù)通過圖組件的ex_data進(jìn)行傳遞,同時(shí)將圖配置的ex屬性設(shè)為true。圖組件初始化后,加載數(shù)據(jù)時(shí)ex屬性為true則使用外部數(shù)據(jù),保存的圖數(shù)據(jù)具有節(jié)點(diǎn)坐標(biāo),在圖渲染完成后,會(huì)使用數(shù)據(jù)中的坐標(biāo)信息更新節(jié)點(diǎn)位置,使接收方查看的圖與分享方圖一致。
研究Linux系統(tǒng)的啟動(dòng)過程是對(duì)其優(yōu)化和定制的基礎(chǔ),通過分析平臺(tái)輔助去了解和認(rèn)識(shí)啟動(dòng)函數(shù),圖形化的調(diào)用圖、詳細(xì)的調(diào)用表與源碼結(jié)合,更直觀認(rèn)識(shí)模塊調(diào)用和函數(shù)信息。
內(nèi)核啟動(dòng)函數(shù)start_kernel所在文件為/init/main.c,在FRCG工具頁面中,選擇內(nèi)核版本和平臺(tái),通過輸入查找,快速找到源路徑/init/main.c,目標(biāo)路徑選為/,配置完整調(diào)用圖自動(dòng)加載,使用調(diào)用圖篩選和拖動(dòng)等功能,實(shí)現(xiàn)調(diào)用如圖5所示,鼠標(biāo)停留在啟動(dòng)函數(shù)節(jié)點(diǎn)上,高亮顯示關(guān)聯(lián)模塊和函數(shù)節(jié)點(diǎn),無調(diào)用關(guān)系路徑和函數(shù)節(jié)點(diǎn)透明度降低,排除干擾。
圖5 內(nèi)核啟動(dòng)函數(shù)調(diào)用
對(duì)于需要分析的模塊,可以通過右鍵菜單中節(jié)點(diǎn)展開、查看函數(shù)調(diào)用表等,獲取詳細(xì)信息。如圖6為查看start_kernel函數(shù)中對(duì)fs模塊的調(diào)用表。
圖6 啟動(dòng)函數(shù)對(duì)fs模塊的調(diào)用列表
調(diào)用表中點(diǎn)擊所在文件和行號(hào)列內(nèi)容可以在新頁面顯示對(duì)應(yīng)源碼,提供研究者分析模塊間調(diào)用關(guān)系的同時(shí)快速確定源碼中函數(shù)所在位置及模塊間調(diào)用關(guān)系。
FRCG工具使研究人員快速查看函數(shù)調(diào)用關(guān)系,區(qū)分模塊間是否存在調(diào)用,跳轉(zhuǎn)查看文件或函數(shù)源碼。傳統(tǒng)源碼分析平臺(tái),對(duì)于調(diào)用的函數(shù)無法提供詳細(xì)信息,遇到重名函數(shù)時(shí),檢索函數(shù),并羅列出該函數(shù)名的全部定義和調(diào)用,用戶需要自行區(qū)分,找到當(dāng)前文件中對(duì)應(yīng)的函數(shù)位置,進(jìn)行查看。
函數(shù)調(diào)用圖模塊的鏈接源碼功能,源數(shù)據(jù)確定的函數(shù)調(diào)用,包含函數(shù)的文件路徑和所在行等信息,用戶可以在右鍵菜單中選擇查看對(duì)應(yīng)源碼,平臺(tái)會(huì)跳轉(zhuǎn)到當(dāng)前顯示節(jié)點(diǎn)的源碼位置,用戶無須分辨重名函數(shù)。
本文FRCG工具針對(duì)DBCG-RTL靜態(tài)函數(shù)調(diào)用圖部分使用前后端分離方式重構(gòu)優(yōu)化,保留原有靜態(tài)調(diào)用圖部分全部功能,并大幅提高調(diào)用圖生成速度,增加系統(tǒng)部署的靈活性。本文使用i5-6500,8 G RAM,Win10-1909搭建測(cè)試平臺(tái),使用VMware 15,分配4核,4 GB內(nèi)存虛擬機(jī)運(yùn)行Ubuntu 1804操作系統(tǒng)、Node.js 12.16.2、MySQL 8作為服務(wù)器;測(cè)試數(shù)據(jù)為Linux-4.15.18內(nèi)核在x64平臺(tái)下的頂層路徑之間調(diào)用關(guān)系。
根據(jù)調(diào)用圖從請(qǐng)求到查看流程,DBCG-RTL中包含服務(wù)器Ruby腳本查詢數(shù)據(jù)庫、處理數(shù)據(jù)、服務(wù)器Ruby腳本渲染SVG圖、網(wǎng)絡(luò)傳輸和用戶瀏覽器顯示,本文測(cè)試階段忽略瀏覽器渲染SVG圖時(shí)間,將處理、渲染、傳輸?shù)姆侄螘r(shí)間進(jìn)行統(tǒng)計(jì);FRCG工具包含Node.js服務(wù)器讀取數(shù)據(jù)庫并處理、請(qǐng)求數(shù)據(jù)傳輸和前端頁面渲染生成調(diào)用圖,將處理、傳輸、渲染的分段時(shí)間進(jìn)行統(tǒng)計(jì),結(jié)果如圖7所示。
由于DBCG-RTL工具Ruby腳本在查詢數(shù)據(jù)庫階段為線性執(zhí)行,大量查詢等待時(shí)間堆積造成處理時(shí)間過長,而渲染階段需要先生成中間文件,存儲(chǔ)到文件系統(tǒng),調(diào)用外部腳本處理生成為SVG圖格式,再次寫入文件存儲(chǔ),最后讀取文件進(jìn)行返回。多次文件讀寫和外部腳本調(diào)用,隨著文件容量的增加造成過長的等待時(shí)間。而FRCG工具,實(shí)現(xiàn)異步讀取數(shù)據(jù)庫,提高查詢速度,查詢完成后直接轉(zhuǎn)換為JSON格式返回,內(nèi)存級(jí)數(shù)據(jù)讀寫,大幅提高處理速度,同時(shí)渲染過程在客戶端進(jìn)行,不占用服務(wù)器的計(jì)算資源,服務(wù)器能夠更快返回?cái)?shù)據(jù)。
對(duì)更大范圍路徑進(jìn)行測(cè)試,將工具階段時(shí)間匯總,統(tǒng)計(jì)處理、渲染、傳輸?shù)目倳r(shí)間,對(duì)比結(jié)果如圖8所示。
圖8 總時(shí)間對(duì)比
增加冪函數(shù)回歸[16]趨勢(shì)線輔助觀察數(shù)據(jù)變化趨勢(shì),如圖8所示,F(xiàn)RCG處理總時(shí)間低于DBCG-RTL總時(shí)間。隨元素?cái)?shù)上升,總時(shí)間差距越大。查看統(tǒng)計(jì)數(shù)據(jù),當(dāng)前測(cè)試平臺(tái)下全部測(cè)試路徑內(nèi):DBCG-RTL工具總時(shí)間平均為273 288 ms,即4 min 33 s,而FRCG總時(shí)間平均為3125 ms即3.1 s。耗時(shí)最長的路徑fs-kernel DBCG-RTL渲染階段用時(shí)5222.512 s,長達(dá)1 h 27 min,而FRCG處理總時(shí)間,只有11.818 s,F(xiàn)RCG處理速度明顯快于DBCG-RTL工具。
對(duì)比兩工具傳輸數(shù)據(jù),DBCG-RTL生成的SVG圖,存在如點(diǎn)擊響應(yīng)的鏈接和渲染后的坐標(biāo)信息等冗余內(nèi)容,同時(shí)XML的標(biāo)簽結(jié)構(gòu)數(shù)據(jù)隨著元素?cái)?shù)量上升而增加,導(dǎo)致數(shù)據(jù)量大;Node處理后的圖數(shù)據(jù),只包含節(jié)點(diǎn)和邊的屬性信息,節(jié)點(diǎn)和邊的跳轉(zhuǎn)事件由頁面動(dòng)態(tài)創(chuàng)建,節(jié)點(diǎn)和邊無需存儲(chǔ)跳轉(zhuǎn)鏈接數(shù)據(jù)。同時(shí)圖的渲染由頁面組件實(shí)現(xiàn),數(shù)據(jù)中無需包含渲染坐標(biāo)等信息。實(shí)現(xiàn)大幅度減少傳輸數(shù)據(jù),并隨著圖上元素?cái)?shù)量的增多,傳輸數(shù)據(jù)量減小的比例更大。
對(duì)數(shù)據(jù)減小率散點(diǎn)數(shù)據(jù),如圖9所示,增加冪函數(shù)回歸[16]趨勢(shì)線輔助,隨著圖中元素?cái)?shù)量增加FRCG傳輸數(shù)據(jù)減小比例越大,對(duì)于全部測(cè)試路徑,最小減少90%傳輸數(shù)據(jù)大小,平均減少93.53%傳輸數(shù)據(jù)大小。
圖9 數(shù)據(jù)減小比
Node.js服務(wù)器開啟歷史記錄,將歷史數(shù)據(jù)寫入數(shù)據(jù)庫,并設(shè)置過期清除。對(duì)比無歷史數(shù)據(jù)時(shí),平均減少72.64%等待時(shí)間。
考慮SVG圖靜態(tài)內(nèi)容存放在服務(wù)器中,用戶訪問已有SVG圖時(shí),直接獲取資源。對(duì)比用戶查看已有SVG圖和存在歷史記錄的Node.js服務(wù)器的加載時(shí)間最值見表5,平均時(shí)間差為506 ms。
表5 DBCG-RTL與FRCG調(diào)用圖加載時(shí)間最值對(duì)比/ms
在實(shí)際分析工作中,研究人員需要經(jīng)常查看的調(diào)用圖大概率存在歷史緩存,而詳細(xì)路徑下函數(shù)關(guān)系圖存在緩存的概率較低。故對(duì)研究人員連續(xù)查看多個(gè)路徑函數(shù)調(diào)用圖的情況進(jìn)行模擬,假設(shè)部分路徑存在歷史數(shù)據(jù),部分路徑?jīng)]有歷史記錄需要計(jì)算,隨機(jī)取10,20,30,40個(gè)路徑,每個(gè)路徑存在歷史數(shù)據(jù)概率為20%,50%,80%,90%,100%,重復(fù)10次取平均得到實(shí)驗(yàn)結(jié)果如圖10所示。
圖10 服務(wù)器存在歷史記錄的加載時(shí)間對(duì)比
當(dāng)緩存概率大于90%時(shí),DBCG-RTL工具才能比FRCG工具更快顯示。連續(xù)多次查看存在歷史緩存的調(diào)用圖時(shí),SVG圖的獲取時(shí)間明顯快于FRCG工具,但SVG圖中包含大量冗余數(shù)據(jù),全部存儲(chǔ)會(huì)占用大量存儲(chǔ)空間。而FRCG工具,能夠在犧牲少量加載時(shí)間的情況下,減少歷史記錄所占用空間,同時(shí)對(duì)于查看無緩存的調(diào)用圖,F(xiàn)RCG能夠大幅提高加載速度。
綜上所述,F(xiàn)RCG工具在調(diào)用圖的數(shù)據(jù)計(jì)算和渲染速度上優(yōu)于DBCG-RTL,同時(shí)網(wǎng)路傳輸數(shù)據(jù)量更小。DBCG-RTL的優(yōu)勢(shì)在于能夠存儲(chǔ)靜態(tài)調(diào)用圖進(jìn)行顯示,F(xiàn)RCG使用緩存數(shù)據(jù)時(shí),仍需在頁面中渲染生成調(diào)用圖,查看調(diào)用圖過程無法避免頁面的渲染過程。
本文將前后端分離框架與分析工具結(jié)合實(shí)現(xiàn)FRCG工具,將調(diào)用圖的生成過程,拆分為后端處理數(shù)據(jù),前端渲染調(diào)用圖,平均減少了83.02%的調(diào)用圖等待時(shí)間。服務(wù)器處理階段,采用Promise對(duì)象異步讀取數(shù)據(jù)庫,提高圖數(shù)據(jù)的處理速度,同時(shí)優(yōu)化傳輸?shù)臄?shù)據(jù)結(jié)構(gòu),平均減小93.53%傳輸數(shù)據(jù)量。前端頁面通過對(duì)數(shù)據(jù)操作實(shí)現(xiàn)切換調(diào)用圖和增量更新調(diào)用圖,提高了調(diào)用圖的靈活性。
FRCG工具主要實(shí)現(xiàn)靜態(tài)調(diào)用數(shù)據(jù)的處理和展現(xiàn),源碼查看由鏈接外部頁面實(shí)現(xiàn),要形成完善的分析工具,需要將多種分析工具整合到工具中,下一步工作目標(biāo)為增加源碼模塊,并實(shí)現(xiàn)源碼模塊與調(diào)用圖和調(diào)用表的有效結(jié)合;同時(shí)增加系統(tǒng)監(jiān)控模塊,通過動(dòng)態(tài)監(jiān)控工具,實(shí)現(xiàn)顯示運(yùn)行中系統(tǒng)調(diào)用,力求實(shí)現(xiàn)靜態(tài)分析與動(dòng)態(tài)分析的結(jié)合。