Apache火花作為編譯器:加入每秒十億行上一台筆記本電腦
2016年5月23日 在工程的博客
當我們的團隊在磚計劃即將到來的Apache 2.0版本,我們貢獻我們設定了一個雄心勃勃的目標,問自己:Apache火花已經很快,但我們能讓它快10倍嗎?
這個問題讓我們從根本上重新思考我們建立了火花身體執行層。當你看到在現代數據引擎(例如火花或其他MPP數據庫),大多數CPU周期的花在無用的工作,如製作虛擬函數調用或閱讀或寫作中間數據CPU緩存或內存。通過減少CPU周期的數量優化性能浪費在無用的現代編譯器的工作已經長期關注。
Apache 2.0火花將船第二代鎢引擎。建立在思想與現代編譯器和MPP數據庫和應用於數據處理查詢,鎢發出(火花- 12795)在運行時優化字節碼,瓦解整個查詢到一個單一的功能,消除虛函數調用和中間數據利用CPU寄存器。由於這種簡化策略,稱為“舞台代碼生成”我們顯著改善CPU效率和增益性能。
過去:火山迭代器模式
之前我們深入了解舞台代碼生成的細節,讓我們重新審視目前火花(和大多數數據庫係統)是如何工作的。讓我們用一個簡單的查詢,說明這個掃描單個表和計算元素的數量與給定屬性值:
評估這個查詢,舊版本(1. x)的火花杠杆流行經典查詢評估策略基於迭代器模式(通常被稱為火山模型)。在這個模型中,一個查詢包含多個運營商,並且每個運營商提供了一個接口,next ()
一次,返回一個元組中的下一個算子樹。例如,過濾操作符大約在上麵的查詢轉化為下麵的代碼:
類濾波器(孩子:運營商謂詞:= >布爾(行)
擴展操作符{
def next():行= {
當前var = child.next ()
而(當前= null & & !謂詞(當前)){
當前= child.next ()
}
返回當前
}
}
在每個操作符實現迭代器接口允許查詢執行引擎的優雅組合任意組合運營商,而不必擔心每個運營商都提供不透明的數據類型。因此,火山模型成為了標準數據庫係統在過去的二十年,也是架構用於火花。
火山和手寫代碼
跑題了一點,如果我們問一個大學新生,給她十分鍾在Java中實現上麵的查詢?很可能她會想出迭代循環遍曆輸入的代碼,將計算謂詞和計數的行:
var計算= 0
(在store_sales ss_item_sk) {
如果(ss_item_sk = = 1000) {
數+ = 1
}
}
上麵的代碼編寫專門回答一個給定的查詢,顯然不是“可組合。“但如何two-Volcano生成和手寫代碼比較性能?一方麵,我們有選擇的體係結構可組合性的火花和大多數數據庫係統。另一方麵,我們有一個簡單的程序由一個新手在10分鍾內寫的。我們運行了一個簡單的基準測試,比較了“大學新生”版本的程序和火花程序執行上麵的查詢對鑲木地板使用單個線程數據在磁盤上:
如您所見,“大學新生”手寫版本是一個數量級的速度比火山模型。原來的6行Java代碼進行了優化,有以下原因:
- 沒有虛函數文件:在火山模型中,處理元組需要調用
next ()
函數至少一次。這些函數調用編譯器實現的虛函數分派(通過vtable)。手寫代碼,另一方麵,沒有一個函數調用。雖然虛函數調度集中的優化在現代計算機體係結構中,它仍然成本可以將多個CPU指令和非常緩慢,特別是當調度數十億倍。 - 中間數據在內存和CPU寄存器:在火山模型中,每一次操作符將一個元組傳遞給另一個運營商,它需要把內存中的元組(函數調用堆棧)。相比之下,手寫版本編譯器(JVM JIT在這種情況下)實際上CPU寄存器中的中間數據的地方。再次,周期需要CPU訪問數據在內存中比在大數量級的寄存器。
- 循環展開和SIMD:現代編譯器和cpu是令人難以置信的高效率當編譯和執行簡單的for循環。編譯器會自動展開簡單的循環,甚至產生SIMD指令來處理多個元組每個CPU指令。cpu包括功能,如管道、預取指令重新排序,使執行簡單的循環效率。然而,這些編譯器和cpu不偉大的優化複雜的函數調用圖,這依賴於火山模型。
這裏的關鍵論點是,手寫代碼被編寫具體運行查詢並沒有別的,因此它可以利用已知的所有信息,導致優化代碼,消除虛函數分派,在CPU寄存器保存中間數據,可以通過底層硬件進行優化。
未來:舞台代碼生成
從上麵觀察,自然為我們下一步是探討自動生成的可能性手寫的代碼在運行時,我們稱之為“舞台代碼生成。“這想法是受托馬斯·諾伊曼的開創性VLDB 2011年的論文現代硬件有效編製高效的查詢計劃。為更多的細節在紙上,阿德裏安鼠鳥協調出版晨報博客上的評論今天。
我們的目標是利用舞台代碼生成引擎可以實現手寫代碼的性能,但提供了一個通用引擎的功能。而不是依靠運營商處理數據在運行時,這些操作符生成代碼在運行時和崩潰的每個片段的查詢,在可能的情況下,成一個單一的函數並執行生成的代碼。
例如,在上麵的查詢中,整個查詢是一個單級,火花將生成以下JVM字節碼(在Java代碼的形式說明)。更複雜的查詢將導致多個階段,因此多個不同的功能所產生的火花。
的解釋()
下麵的表達式功能擴展了舞台代碼生成。在解釋輸出,當操作員(*)有一個明星,舞台啟用代碼生成。在下列情況下,範圍、過濾和舞台的兩個總量都是運行代碼生成。交流,然而,沒有實現舞台代碼生成,因為它是通過網絡發送數據。
火花。範圍(1000年)。過濾器(“id > 100”).selectExpr (“總和(id)”).explain ()
= = = =物理計劃*總(函數= (總和(id# 201 l)))+ - SinglePartition交換,沒有一個+ - *總(函數= (總和(id# 201 l)))+ - *過濾器(id# 201 l > 100)+ - *範圍0,1,3,1000年,(id# 201 l)
你們已經密切關注火花的發展可能會問以下問題:“我聽說過代碼生成自Apache 1.1火花這篇博客。這次怎麼不同呢?“過去,類似於其他MPP查詢引擎,火花隻應用代碼生成表達式求值和僅限於少數運營商(如項目,過濾器)。代碼生成,在過去隻有加快評估表達式如“1 +”,而今天舞台代碼生成整個查詢計劃的生成代碼。
向量化
舞台代碼生成技術對大型特別有效的執行簡單的查詢,可預見的操作大型數據集。然而,這是不可行的情況下生成代碼來查詢整個熔合成一個單一的函數。操作可能太複雜(例如解析CSV或鑲花解碼),或者可能有情況下當我們結合第三方組件,不能將他們的代碼集成到我們生成的代碼(例子的範圍可以從調用Python / R卸載GPU計算)。
以提高性能在這些情況下,我們采用另一種方法稱為“向量化。“這裏的想法是,而不是一次處理一行數據,引擎批次倍數行柱狀的格式,和每個操作符使用簡單的循環來遍曆數據在一個批處理。每一個next ()
調用將返回一個元組批,掩蓋了虛函數分派的成本。這些簡單的循環也會使編譯器和cpu與前麵提到的好處更有效地執行。
作為一個例子,對於一個表有三個列(id、名稱、分數),以下說明row-oriented格式和用於格式的內存布局。
這種風格的處理,由柱狀數據庫係統如MonetDB C-Store,將實現兩個前麵提到的三個點(幾乎沒有虛函數分派和自動循環展開/ SIMD)。然而,它仍然需要把中間數據內存而不是讓他們在CPU寄存器。因此,我們使用向量化隻有當舞台代碼生成是不可能的。
例如,我們實現了一個新的矢量化鋪讀者,減壓和解碼列批次。當解碼整數列(在磁盤上),這個新的讀者大概是9倍non-vectorized一:
在未來,我們計劃使用向量化等更多的代碼路徑的UDF Python / R的支持。
性能基準測試
我們有測量的時間(納秒)需要處理一個元組在一個核心的一些運營商在Apache 1.6和Apache 2.0火花,火花,下表是一個比較新的鎢引擎的力量。火花1.6包含表達式代碼生成技術,也在今天使用一些先進的商業數據庫。
成本每一行(在納秒,單線程)
原始的 | 火花1.6 | 火花2.0 |
---|---|---|
過濾器 | 15 ns | 1.1 ns |
和w / o組 | 14 ns | 0.9 ns |
和w /組 | 79納秒 | 10.7 ns |
散列連接 | 115納秒 | 4.0 ns |
排序熵(8位) | 620納秒 | 5.3 ns |
排序熵(64位) | 620納秒 | 40 ns |
分類合並加入 | 750納秒 | 700納秒 |
鑲木地板解碼(單個整數列) | 120納秒 | 13 ns |
我們調查客戶的工作負載和舞台實現代碼生成最beplay体育app下载地址常用的運營商,如過濾、聚合,和散列連接。正如你所看到的,許多核心運營商與舞台代碼生成快一個數量級。然而,一些分類合並等運營商加入天生慢,優化更加困難。
需要不到一秒執行散列連接操作10億元組在磚平台(與英特爾Haswell處理器3芯)以及2013年的Macbook Pro(移動Haswell英特爾i7)。Beplay体育安卓版本
端到端查詢這個新引擎是如何工作的?除了舞台代碼生成和向量化,很多工作也進入改善催化劑優化器等通用查詢優化nullability傳播。我們做了一些初步分析使用TPC-DS查詢比較火花1.6和2.0即將到來的火花:
這是否意味著你的工作量會神奇地變成十倍一旦升級到火花2.0嗎?不一定。雖然我們相信新的鎢引擎實現最好的體係結構在數據處理性能工程,重要的是要理解,不是所有工作負載可以受益到相同的程度。例如,可變長度的數據類型,如字符串是自然更昂貴的操作,和一些工作負載是由其他因素有界從I / O吞吐量元數據操作。以前的工作負載有界通過CPU效率會觀察最大的收益,和轉向更多的I / O,而以前,I / O工作負載不太可能觀察收益。
結論
這篇文章中描述的大部分工作已經提交到Apache火花的代碼庫,開槽為即將到來的火花2.0版本。舞台的JIRA票代碼生成可以在火花- 12795,而向量化的票可以在火花- 12992。
回顧一下,這篇文章描述了第二代鎢執行引擎。通過一個稱為舞台的技術代碼生成引擎將(1)消除虛函數分派(2)中間數據從內存移到CPU寄存器和(3)利用現代CPU通過循環展開和SIMD功能。通過一個稱為向量化的技術,發動機也將加快操作過於複雜的代碼生成。對於許多核心運營商在數據處理中,新引擎數量級的速度。在未來,考慮到執行引擎的效率,大部分我們的工作將轉向性能優化I / O效率和更好的查詢計劃。
我們對取得的進步感到興奮,希望你能喜歡這些改進。嚐試一些免費,注冊一個帳戶磚Community Edition。