鯤鵬BoostKit OminiRuntime:高效的數(shù)據(jù)Runtime底座
分析引擎在為企業(yè)提供低延遲和低成本的實(shí)時(shí)分析方面發(fā)揮著至關(guān)重要的作用。隨著數(shù)據(jù)規(guī)模和多樣性爆炸式增長(zhǎng),企業(yè)應(yīng)用要求分析系統(tǒng)具備高并發(fā)查詢和高吞吐,同時(shí)支持對(duì)結(jié)構(gòu)化和非結(jié)構(gòu)化數(shù)據(jù)的查詢。
為了滿足這些要求,分析引擎和數(shù)據(jù)庫(kù)通常依賴于將查詢計(jì)劃編譯為本機(jī)代碼。手動(dòng)編寫算子的方式,如filter,join和group by,通常包含處理不同參數(shù)和數(shù)據(jù)類型所需的控制流。本機(jī)代碼生成的目的是通過消除不必要的代碼并將其專門用于底層平臺(tái),從而最大限度地減少指令數(shù)量。
然而,上述方案在易用性和硬件兼容性方面往往存在局限性,我們總結(jié)為三點(diǎn):
1. 數(shù)據(jù)獲?。簺]有有效的方法過濾非必要的數(shù)據(jù),大量計(jì)算資源被浪費(fèi)
2. 數(shù)據(jù)計(jì)算:算子通過JAVA、Scala等高級(jí)語言實(shí)現(xiàn),無法充分發(fā)揮算力;算子優(yōu)化困難
3. 數(shù)據(jù)層優(yōu)化:要解決端到端流程中的問題,各個(gè)引擎需要做垂直優(yōu)化
為此,鯤鵬應(yīng)用使能套件BoostKit中提供了大數(shù)據(jù)的Runtime底座——OmniRuntime, 通過五個(gè)核心組件,如下圖所示,實(shí)現(xiàn)針對(duì)數(shù)據(jù)接入、傳輸、計(jì)算全周期開展性能優(yōu)化,提升大數(shù)據(jù)分析場(chǎng)景的性能提升30%以上。
圖. 大數(shù)據(jù)的Runtime底座——OmniRuntime
圖. OmniRuntime核心組件示意圖
●OmniJit:一個(gè)透明、易于使用的即時(shí)編譯框架,不需要對(duì)任何低級(jí)代碼生成框架(如LLVM或Janino)的了解。
●OmniVec:一種列式內(nèi)存格式,提供高性能內(nèi)存訪問、全內(nèi)存生命周期管理和內(nèi)置SIMD操作。它還支持所有常用的數(shù)據(jù)類型,如int、double、varchar和decimal等。
●OmniOperator:native 算子庫(kù),充分利用當(dāng)今異構(gòu)計(jì)算環(huán)境中可用硬件的計(jì)算能力,與OmniJit結(jié)合使用時(shí),能夠動(dòng)態(tài)地適應(yīng)工作負(fù)載、參數(shù)和數(shù)據(jù)配置文件,以實(shí)現(xiàn)最佳性能。
●OmniCache:一種關(guān)系型緩存,性能優(yōu)于傳統(tǒng)的面向塊的緩存,命中率極高。
●OmniData:快速數(shù)據(jù)訪問和協(xié)作層,提供數(shù)據(jù)層和計(jì)算層之間的雙向通信和數(shù)據(jù)傳輸。
1 OmniJit
OmniJit組件對(duì)分析工作負(fù)載的整體性能提高做出了重大貢獻(xiàn)。
OmniJit旨在為普通開發(fā)人員提供即時(shí)編譯支持。它提供了一個(gè)易于使用的高級(jí)語言框架,如C/C++。OmniJit自動(dòng)識(shí)別運(yùn)算符中最關(guān)鍵的性能代碼部分并優(yōu)化它們。生成的運(yùn)算符是專門使用查詢、運(yùn)行時(shí)和硬件特定的計(jì)算機(jī)代碼的。OmniJit依賴于運(yùn)行時(shí)信息來基于查詢上下文應(yīng)用最佳優(yōu)化。這可以是數(shù)據(jù)集基數(shù)、列大小、數(shù)據(jù)類型、可用硬件(SIMD、加速器等)以及許多其他信息,以產(chǎn)生最佳運(yùn)算符優(yōu)化。
通過使用OmniJit,分析引擎開發(fā)人員將不再需要與LLVM或Janino等系統(tǒng)提供的復(fù)雜低級(jí)API交互,以提取最佳性能。
圖2. OmniJit分支裁剪和循環(huán)展開優(yōu)化
2 OmniOperator
OmniOperator表示處理特定查詢數(shù)據(jù)的計(jì)算邏輯代碼。SQL查詢可以由許多不同的算子組成,OmniJit負(fù)責(zé)動(dòng)態(tài)優(yōu)化它們。OmniJit優(yōu)化了C++算子,以生成具有最小執(zhí)行指令計(jì)數(shù)的可執(zhí)行文件。
算子接口的結(jié)構(gòu)與火山模型相似,因?yàn)樗裱愃频慕涌谏芷冢簩?shí)例化、AddInput、GetOuput和Close。所有OmniOperators都提供相同的標(biāo)準(zhǔn)接口,實(shí)現(xiàn)對(duì)分析引擎不透明。
通過利用標(biāo)準(zhǔn)接口,我們可以輕松地將這些運(yùn)算符暴露給上層計(jì)算引擎。此外,它還幫助我們提供一致的開發(fā)生命周期體驗(yàn),同時(shí)允許跨各種分析平臺(tái)的可移植性。開發(fā)人員可以讓OmniJit使用自動(dòng)化方法優(yōu)化運(yùn)算符?;蛘?,他可以指導(dǎo)優(yōu)化策略,如參數(shù)固定、循環(huán)開發(fā)和代碼中特定核心方法的矢量化自適應(yīng)執(zhí)行。
與本機(jī)平臺(tái)運(yùn)算符相比,生成的OmniOperators執(zhí)行的指令計(jì)數(shù)更少,資源消耗更低,開發(fā)開銷也更低。下圖顯示了Java Analytics平臺(tái)中的整體OmniOperator生命周期。由于大多數(shù)分析引擎都是用Java編碼的,我們還提供了一個(gè)JNI接口來促進(jìn)集成。
圖3. OmniOperator引擎與Native Operator的交互
3 OmniVector
OmniVector是OmniRuntime的另一個(gè)組件。OmniVector定義了標(biāo)準(zhǔn)的列式內(nèi)存格式。OmniVector設(shè)計(jì)為可移植的、獨(dú)立于列的內(nèi)存數(shù)據(jù)格式。OmniVector支持豐富的數(shù)據(jù)類型系統(tǒng),旨在滿足各種分析數(shù)據(jù)系統(tǒng)的需求。這種內(nèi)存數(shù)據(jù)格式為數(shù)據(jù)密集型應(yīng)用程序提供高性能和高可擴(kuò)展性。
OmniVector的核心代碼是在C++中實(shí)現(xiàn)的,帶有高級(jí)語言綁定,以實(shí)現(xiàn)交叉兼容性。它提供了一個(gè)異步接口,允許讀取和寫入操作由各種組件并行進(jìn)行。這允許我們?cè)趯懭牖虺志没僮鞅焕^續(xù)時(shí)公開OmniVector的內(nèi)容。
下圖顯示了OmniVec的整體架構(gòu)。
圖4. OmniVec Binging和Native架構(gòu)
基于作用域的全生命周期管理的OmniVector不僅消除了內(nèi)存泄漏的可能性,而且提供了高性能的內(nèi)存訪問。每個(gè)OmniVector在其生命周期中都會(huì)經(jīng)歷幾個(gè)步驟。每個(gè)步驟都由OmniVctor操作觸發(fā):
1. 作用域創(chuàng)建:為了進(jìn)行有效的內(nèi)存管理并避免頁(yè)面故障開銷,向量在特定的執(zhí)行作用域內(nèi)分配。這允許高效的內(nèi)存池,從而最大限度地減少內(nèi)存管理開銷。
2. OmniVector分配:通過使用上面創(chuàng)建的范圍,開發(fā)人員現(xiàn)在可以分配新的向量。
3. OmniVector 修改:API支持Set和Put操作。前者在特定對(duì)應(yīng)的索引位置操作單個(gè)值。后者是批處理put方法,在該方法中,數(shù)組插入到指定的開始位置。
4. OmniVector讀?。号c修改一樣,我們支持單值檢索或批處理操作。
5. OmniVector釋放:一旦不使用向量,就可以將其釋放到作用域內(nèi)存池
6. 作用域釋放:釋放所有向量后,我們可以釋放作用域和關(guān)聯(lián)的內(nèi)存池。
由于此設(shè)計(jì),OmniVector支持以下功能:
●零拷貝操作
●支持?jǐn)?shù)據(jù)生命周期管理和內(nèi)存泄漏檢測(cè)。
●支持復(fù)雜的數(shù)據(jù)結(jié)構(gòu),如MAP、列表和結(jié)構(gòu)。
●SIMD指令優(yōu)化和硬件加速接口
●自動(dòng)溢出到存儲(chǔ)
●高性能內(nèi)存分配和池化。
4 OmniJit、OmniVctor和OmniOperator性能數(shù)據(jù)
我們?cè)趏penLooKeng、Spark和Hive等流行的大數(shù)據(jù)系統(tǒng)中集成了OmniRuntime和OmniJit。然后,我們使用TPC-H在openLooKeng上進(jìn)行了基準(zhǔn)測(cè)試,實(shí)驗(yàn)結(jié)果表明集成了Omniruntime框架的性能明顯優(yōu)于原始分析引擎。
圖5. OmniJit優(yōu)化的算子效果
5 OmniCache
OmniCache是OmniRuntime中的關(guān)系型緩存。OmniCache不僅緩存數(shù)據(jù),還維護(hù)數(shù)據(jù)與緩存中的數(shù)據(jù)之間的關(guān)系。OmniCache構(gòu)造虛擬數(shù)據(jù)集,緩存從物理集數(shù)據(jù)或其他虛擬數(shù)據(jù)集派生的關(guān)系數(shù)據(jù),并使用SQL SELECT語句定義用于緩存的關(guān)系數(shù)據(jù)。
這種方法比傳統(tǒng)的基于文件塊的緩存系統(tǒng)具有優(yōu)勢(shì)。傳統(tǒng)緩存系統(tǒng)中整個(gè)文件塊必須緩存或丟棄,這可能會(huì)導(dǎo)致許多數(shù)據(jù)換入和換出操作,導(dǎo)致緩存命中率非常低。
為了維護(hù)關(guān)系信息,OmniCache將其狀態(tài)和結(jié)構(gòu)信息提供給查詢優(yōu)化器,以最大限度地提高命中率。公開的緩存元數(shù)據(jù)有助于分析引擎優(yōu)化查詢計(jì)劃,并首先訪問緩存中的數(shù)據(jù),而不是通過慢速數(shù)據(jù)存儲(chǔ)。此外,緩存還能夠存儲(chǔ)中間查詢結(jié)果。它允許通過使查詢計(jì)劃程序直接訪問先前計(jì)算的數(shù)據(jù),而不是執(zhí)行如圖6所示的完整查詢計(jì)劃來加速操作。
圖6. OmniCache
Omnicache具備以下功能:
●緩存管理:通過使用物化視圖命令生成和管理物化視圖。
●SQL重寫:SQL重寫使用關(guān)系代數(shù)和成本模型執(zhí)行,以有效利用緩存數(shù)據(jù)。
●緩存存儲(chǔ):全局內(nèi)存池的關(guān)系型緩存,基于堆外內(nèi)存實(shí)現(xiàn),可進(jìn)行高效的數(shù)據(jù)存儲(chǔ)和訪問。
6 OmniData
OmniData是OmniRuntime的快速數(shù)據(jù)訪問和協(xié)作層,旨在減少數(shù)據(jù)存儲(chǔ)層和計(jì)算層之間的數(shù)據(jù)傳輸,這在現(xiàn)代存算分離的數(shù)據(jù)中心中非常有效。
OmniData不會(huì)直接從存儲(chǔ)端加載文件,然后處理數(shù)據(jù),而是將特定操作卸載到存儲(chǔ)端進(jìn)行近數(shù)據(jù)處理。目標(biāo)是減少所需的網(wǎng)絡(luò)通信量和整體計(jì)算量。
OmniData通過將查詢執(zhí)行劃分為幾個(gè)與數(shù)據(jù)分布匹配的階段來實(shí)現(xiàn)這一目標(biāo)。然后,代表子處理操作的每個(gè)階段都被發(fā)送到存儲(chǔ)節(jié)點(diǎn)附近或存儲(chǔ)節(jié)點(diǎn)上執(zhí)行。親和性調(diào)度用于避免存儲(chǔ)節(jié)點(diǎn)計(jì)算能力過載,并保持較高的整體吞吐量。階段性操作允許本地?cái)?shù)據(jù)加載和處理。
圖. OmniData實(shí)現(xiàn)原理
未來展望
OmniRuntime使用OmniJit、OminVector、OmniOperator、OmniCache和OmniData的組合,為分析平臺(tái)提供通用的數(shù)據(jù)處理基礎(chǔ),為不同分析引擎提供具有上下文優(yōu)化功能的通用引擎,顯著減輕創(chuàng)建自定義優(yōu)化的負(fù)擔(dān),并支持異構(gòu)硬件環(huán)境。
OmniRuntime持續(xù)提供強(qiáng)大的數(shù)據(jù)處理能力,使數(shù)據(jù)分析引擎能夠滿足高并發(fā)、高吞吐量、結(jié)構(gòu)化和非結(jié)構(gòu)化查詢的業(yè)務(wù)需求。未來,OmniRuntime將繼續(xù)聚焦更多的功能實(shí)現(xiàn),如decimal類型支持、UDF框架、表達(dá)式優(yōu)化,以及實(shí)現(xiàn)向量化優(yōu)化等。
歡迎大家登錄hikunpeng.com——鯤鵬社區(qū)鯤鵬BoostKit專區(qū)了解更多關(guān)于OmniRuntime的詳細(xì)信息。