Accelerating or Complicating PHP Execution by LLVM Compiler Infrastructure Jim Huang ( 黃敬群 ) Developer, 0xlab jserv@0xlab.org PHPConf.TW / Nov 12, 2011
到底要講什麼?
如果產能是我們砍掉重練 那我就讓你們看見直譯的驕傲
PHP 巴萊 ( 真實的 PHP) • PHP 5 具備物件導向設計的語言特徵 • PDO = PHP Data Objects • 自 PHP 4 , PHP 已是編譯型語言 • 在 2000 發布 PHP4 前, PHP 的解析與執 行都是透過 PHP 直譯器 • PHP4 引進 Zend engine • Zend engine/VM 內部處理 bytecode ,並 允許特定的快取擴充套件,或統稱「 PHP 加 速器」,來進一步執行 PHP • PHP → bytecode • bytecode → 加速器執行
PHP 快 ( 加速 ) 來 ( 廣泛貼近 )
現有的 PHP 加速器 • PHC (PHP Open Source Compiler) http://www.phpcompiler.org/ • HipHop for PHP, Facebook http://wiki.github.com/facebook/hiphop-php/ • Roadsend PHP • pcc http://code.roadsend.com/pcc • Raven ( 以 LLVM 重寫 ) http://code.roadsend.com/rphp • 以及其他眾多商業解決方案
來源 :: http://terrychay.com/article/hiphop-for-faster-php.shtml/4 來源 http://terrychay.com/article/hiphop-for-faster-php.shtml/4
相關議程: 〈窮得只剩下 Compiler 〉 OSDC.tw 2009 http://www.slideshare.net/jserv/what-can-compilers-do-for-us
相關議程: 〈身騎 LLVM , 過三關: 淺談編譯器技術的嶄新應用〉 TOSSUG 2009 http://www.slideshare.net/jserv/llvm-introduction 相關議程: 〈 Applied Computer Science Concepts in Android 〉 台大資訊系 2010 http://www.slideshare.net/jserv/applied-computer-science-concepts-in-android 相關議程: 〈 Build Programming Runtime with LLVM 〉 OSDC.tw 2011 http://www.slideshare.net/jserv/build-programming-language-runtime-with-llvm
提綱 (1) 因應需求的 LLVM 架構 (2) 結合 PHP 到 LLVM (3) 應用型態
因應需求的 LLVM 編譯器架構
Compiler 領導技術的時代 • 運算模式已大幅改觀 • Framework-driven • SIMD/vectorization, SMP/multi-core • 虛擬化 (Virtualization) 技術的時代 → 更多元、更安全、更有效率地使用硬體 • 非對稱運算環境 • LLVM 的大一統宏願 案例: Portable Native Client, OpenCL (GPGPU)
到處都有 VM Java Virtual Machine (JVM) Tamarin (ActionScript) .NET Common Language Valgrind (C++) Runtime (CLR) Lua Smalltalk TrueType Squeak Dalvik Parrot (Perl 6) Adobe Flash (AVM2) Python p-code (USCD Pascal) YARV (Ruby 1.9) Zend Rubinius RenderScript (Android) 14 LLVM 可作為上述的編譯器應用的根基
LLVM • Low-Level VM → bit-code • 完整的編譯器基礎建設 • 可重用的、用以建構編譯器的軟體元件 • 允許更快更完整的打造新的編譯器 • static compiler, JIT, trace-based optimizer, … • 開放的編譯器框架 • 多種程式語言支援 • 高彈性的自由軟體授權模式 (BSD License) • 活躍的開發 (Apple + Google + Qualcomm) • 豐富的編譯輸出: C, ARM, x86, PowerPC, …
豐富的工具集 Assemblers, automatic debugger, linker, code generator, compiler driver, modular optimizer, …
GCC vs. LLVM GCC LLVM C, C++, Obj-C, Fortran, Java, Ada, ... C, C++, Obj-C x86, ARM, MIPS, PowerPC, … binutils (ld as) BSD-Style License JIT/Interpreter Compiler Driver
Frontend LLVM IR Backend
Frontend LLVM IR Backend
BitCode + Optimizer LTO: Link-Time Optimization LTO: Link-Time Optimization BitCode main.bc Inter-precedual BitCode Linker BitCode Analysis Transforms mod.bc BitCode BitCode BitCode parser writer main.lto.bc BitCode Analysis Transforms BitCode BitCode main.opt.bc mod.opt.bc
LLVM Code Generation libLLVM BitCode Machine main.lto.bc Analysis x86 組語 BitCode Machine main.s BitCode parser Instr Machine Asm Transforms Emitter Execution Transform Transform Register Engine CodeGen Machine SDNode Allocation InterPreter Instr ARM.td InstrInfo Register Instruction Instruction X86.td Subtarget [C++] Selection Scheduler InstrInfo Frame Register main.cpp [C] Lowering x86 Subtarget CallbackUtils main.c SDNode CallingConv Frame Transforms Lowering Selection DAG CallingConv Selection DAG
先從 Hello World 開始 • 完整的 Compiler Driver $ clang hello.c ­o hello • 生成 IR $ clang ­O3 ­emit­llvm hello.c ­c ­o hello.bc • 以 Just-In-Time compiler 模式執行 BitCode $ lli hello.bc Getting Started with the LLVM System Getting Started with the LLVM System http://llvm.org/docs/GettingStarted.html http://llvm.org/docs/GettingStarted.html
#include <stdio.h> #include <stdio.h> int main(int argc, char *argv[]) int main(int argc, char *argv[]) { { printf("Hello world!n"); printf("Hello world!n"); return 0; return 0; } } 函式 printf() 後方僅有一個 函式 printf() 後方僅有一個 • 反組譯 BitCode 字串參數,前端預設將其 字串參數,前端預設將其 轉換為 puts() $ llvm­dis < hello.bc 轉換為 puts()   ; ModuleID = '<stdin>'   ; ModuleID = '<stdin>'   target datalayout = "e­p:32:32:32­...   target datalayout = "e­p:32:32:32­...   target triple = "i386­pc­linux­gnu"   target triple = "i386­pc­linux­gnu"   @str = internal constant [13 x i8] c"Hello world!00"   @str = internal constant [13 x i8] c"Hello world!00"   define i32 @main(i32 %argc, i8** nocapture %argv) nounwind {   define i32 @main(i32 %argc, i8** nocapture %argv) nounwind {   entry:   entry:     %puts = tail call i32 @puts(i8* getelementptr inbounds ([13 x i8]* @str, i32 0, i32 0))     %puts = tail call i32 @puts(i8* getelementptr inbounds ([13 x i8]* @str, i32 0, i32 0))     ret i32 0     ret i32 0   }   }   Declare i32 @puts(i8* nocapture) nounwind   Declare i32 @puts(i8* nocapture) nounwind • 輸出 x86 後端組合語言 $ llc hello.bc ­o hello.s
LLVM 給予無限可能 C/C++/ libClang AST Obj-C BitCode LibLLVM Optimizer BitCode Arch.td libLLVM xxx.s CodeGenerator
提供 IDE 的模組化 有了 AST 後,即可針對 靜態編譯解析器 可用許多程式語言 語言特性,做出特定的應用 撰寫 BitCode 生成 器 ( 前端編譯器 ) C/C++/ libClang ,如 PerlObj-C module AST BitCode 其他語言 系統優化處理 LibLLVM Optimizer 作為其他語言的 Source-to-source 特定的後端架構。 轉換器 可以是硬體或軟體 其他語言 BitCode Arch.td LibLLVM xxx.s CodeGenerator 可增添其他模組,如 Polyhedral optimization 針對後端硬體的 Selection DAG
Xcode OpenCL Compiler OpenCL → Haskell → Clay → C/C++/ libClang AST Obj-C Crack → StrengthReduction BitCode Profile-gen/use 其他語言 AliasAnalysis LibLLVM Optimizer → JavaScript FPGA; → Java ByteCode GPGPU 其他語言 BitCode → CLI → PTX Arch.td LibLLVM regaloc=Pazzle|Graph xxx.s CodeGenerator ObjectCodeEmitter Polly
整合 PHP 到 LLVM 架構
Zend VM 概況 (1) • 依循傳統 SDT (Syntax- Directed Translation) 編譯器 設計方法建構 • 解譯 bytecode • 欠缺進階的編譯器優化機制
Zend VM 概況 (2) • PHP bytecode 使用單純 的表示法,無強制的標準 • 部份資訊如 class 定義, 並未包含在 bytecode
Zend VM 概況 (3)   <?php   <?php   if (1 > 2)   if (1 > 2)         $a = 2 * 3;         $a = 2 * 3;   else   else         $a = 2 * 4;         $a = 2 * 4;   echo $a;   echo $a;   ?>   ?>
Zend + LLVM op_block: op_block: %execute_data = call @phpllvm_get_execute_data(%1) %execute_data = call @phpllvm_get_execute_data(%1) %execute_result = call @ZEND_IS_SMALLER_HANDLER(%execute_data) %execute_result = call @ZEND_IS_SMALLER_HANDLER(%execute_data) switch i32 %execute_result, label %op_block1 [[ switch i32 %execute_result, label %op_block1 i32 1, label %pre_vm_return i32 1, label %pre_vm_return i32 2, label %pre_vm_enter i32 2, label %pre_vm_enter i32 3, label %pre_vm_leave i32 3, label %pre_vm_leave ]]   <?php   <?php   if (1 > 2)   if (1 > 2)         $a = 2 * 3;         $a = 2 * 3;   else   else         $a = 2 * 4;         $a = 2 * 4;   echo $a;   echo $a;   ?>   ?>
PHP + LLVM • PECL::LLVM → Zend bytecode to LLVM assembly compiler, unmaintained http://pecl.php.net/package/llvm Compiles Zend bytecode to LLVM assembly and then into optimized machine code. • Roadsend PHP / Raven • Static analyzer which dumps (in XML) • Tokens / AST / Generated IR • Various analysis passes • Port of phc optimizer passes
PHP + LLVM • HipHop for PHP 僅能執行小部份的 PHP 程 式,而且無法有效佈署 (deployment; 輸出 為 POSIX C++ code) • PHP 不該侷限於伺服器端的應用 • 開發工具的整合 • 透過 LLVM 的 Polly 與 LTO (Link-Time Optimization) ,可進一步優化 Zend bytecode → LLVM bitcode 的執行 • memcache / MP / GPGPU
架構於 LLVM 的程式語言實做 (1) • Unladen Swallow (Google): faster Python $ ./perf.py -r -b call_simple --args "-j always," ../q2/python ../q3/python • Min: 1.618273 -> 0.908331: 78.16% faster • Avg: 1.632256 -> 0.924890: 76.48% faster http://code.google.com/p/unladen-swallow • GHC/Haskell's LLVM codegen • 3x faster in some cases http://donsbot.wordpress.com/2010/02/21/ smoking-fast-haskell-code-using-ghcs-new-llvm-codegen/ • LLVM-Lua : JIT/static Lua compiler • http://code.google.com/p/llvm-lua/ 34
架構於 LLVM 的程式語言實做 (2) • IcedTea Version of Sun's OpenJDK (RedHat) • Zero: processor-independent layer that allows OpenJDK to build and run using any processor • Shark: Zero's JIT compiler: uses LLVM to provide native code generation without introducing processor-dependent code. http://icedtea.classpath.org • Emscripten • LLVM-to-JavaScript compiler • It takes LLVM bitcode and compiles that into JavaScript, which can be run on the web (or anywhere else JavaScript can run). http://code.google.com/p/emscripten/ 35
http://0xlab.org

Accelerating or Complicating PHP execution by LLVM Compiler Infrastructure

  • 1.
    Accelerating or Complicating PHP Execution by LLVM Compiler Infrastructure Jim Huang ( 黃敬群 ) Developer, 0xlab jserv@0xlab.org PHPConf.TW / Nov 12, 2011
  • 2.
  • 4.
  • 5.
    PHP 巴萊 (真實的 PHP) • PHP 5 具備物件導向設計的語言特徵 • PDO = PHP Data Objects • 自 PHP 4 , PHP 已是編譯型語言 • 在 2000 發布 PHP4 前, PHP 的解析與執 行都是透過 PHP 直譯器 • PHP4 引進 Zend engine • Zend engine/VM 內部處理 bytecode ,並 允許特定的快取擴充套件,或統稱「 PHP 加 速器」,來進一步執行 PHP • PHP → bytecode • bytecode → 加速器執行
  • 6.
    PHP 快 ( 加速 ) 來 ( 廣泛貼近 )
  • 7.
    現有的 PHP 加速器 •PHC (PHP Open Source Compiler) http://www.phpcompiler.org/ • HipHop for PHP, Facebook http://wiki.github.com/facebook/hiphop-php/ • Roadsend PHP • pcc http://code.roadsend.com/pcc • Raven ( 以 LLVM 重寫 ) http://code.roadsend.com/rphp • 以及其他眾多商業解決方案
  • 8.
    來源 :: http://terrychay.com/article/hiphop-for-faster-php.shtml/4 來源http://terrychay.com/article/hiphop-for-faster-php.shtml/4
  • 9.
    相關議程: 〈窮得只剩下 Compiler 〉 OSDC.tw 2009 http://www.slideshare.net/jserv/what-can-compilers-do-for-us
  • 10.
    相關議程: 〈身騎 LLVM , 過三關: 淺談編譯器技術的嶄新應用〉 TOSSUG 2009 http://www.slideshare.net/jserv/llvm-introduction 相關議程: 〈 Applied Computer Science Concepts in Android 〉 台大資訊系 2010 http://www.slideshare.net/jserv/applied-computer-science-concepts-in-android 相關議程: 〈 Build Programming Runtime with LLVM 〉 OSDC.tw 2011 http://www.slideshare.net/jserv/build-programming-language-runtime-with-llvm
  • 11.
    提綱 (1) 因應需求的 LLVM 架構 (2) 結合 PHP 到 LLVM (3) 應用型態
  • 12.
  • 13.
    Compiler 領導技術的時代 • 運算模式已大幅改觀 • Framework-driven • SIMD/vectorization, SMP/multi-core • 虛擬化 (Virtualization) 技術的時代 → 更多元、更安全、更有效率地使用硬體 • 非對稱運算環境 • LLVM 的大一統宏願 案例: Portable Native Client, OpenCL (GPGPU)
  • 14.
    到處都有 VM Java VirtualMachine (JVM) Tamarin (ActionScript) .NET Common Language Valgrind (C++) Runtime (CLR) Lua Smalltalk TrueType Squeak Dalvik Parrot (Perl 6) Adobe Flash (AVM2) Python p-code (USCD Pascal) YARV (Ruby 1.9) Zend Rubinius RenderScript (Android) 14 LLVM 可作為上述的編譯器應用的根基
  • 15.
    LLVM • Low-Level VM→ bit-code • 完整的編譯器基礎建設 • 可重用的、用以建構編譯器的軟體元件 • 允許更快更完整的打造新的編譯器 • static compiler, JIT, trace-based optimizer, … • 開放的編譯器框架 • 多種程式語言支援 • 高彈性的自由軟體授權模式 (BSD License) • 活躍的開發 (Apple + Google + Qualcomm) • 豐富的編譯輸出: C, ARM, x86, PowerPC, …
  • 16.
    豐富的工具集 Assemblers, automatic debugger,linker, code generator, compiler driver, modular optimizer, …
  • 17.
    GCC vs. LLVM GCC LLVM C, C++, Obj-C, Fortran, Java, Ada, ... C, C++, Obj-C x86, ARM, MIPS, PowerPC, … binutils (ld as) BSD-Style License JIT/Interpreter Compiler Driver
  • 18.
    Frontend LLVM IR Backend
  • 19.
    Frontend LLVM IR Backend
  • 20.
    BitCode + Optimizer LTO: Link-Time Optimization LTO: Link-Time Optimization BitCode main.bc Inter-precedual BitCode Linker BitCode Analysis Transforms mod.bc BitCode BitCode BitCode parser writer main.lto.bc BitCode Analysis Transforms BitCode BitCode main.opt.bc mod.opt.bc
  • 21.
    LLVM Code Generation libLLVM BitCode Machine main.lto.bc Analysis x86 組語 BitCode Machine main.s BitCode parser Instr Machine Asm Transforms Emitter Execution Transform Transform Register Engine CodeGen Machine SDNode Allocation InterPreter Instr ARM.td InstrInfo Register Instruction Instruction X86.td Subtarget [C++] Selection Scheduler InstrInfo Frame Register main.cpp [C] Lowering x86 Subtarget CallbackUtils main.c SDNode CallingConv Frame Transforms Lowering Selection DAG CallingConv Selection DAG
  • 22.
    先從 Hello World開始 • 完整的 Compiler Driver $ clang hello.c ­o hello • 生成 IR $ clang ­O3 ­emit­llvm hello.c ­c ­o hello.bc • 以 Just-In-Time compiler 模式執行 BitCode $ lli hello.bc Getting Started with the LLVM System Getting Started with the LLVM System http://llvm.org/docs/GettingStarted.html http://llvm.org/docs/GettingStarted.html
  • 23.
    #include <stdio.h> #include <stdio.h> int main(int argc, char *argv[]) int main(int argc, char *argv[]) { { printf("Hello world!n"); printf("Hello world!n"); return 0; return 0; } } 函式 printf() 後方僅有一個 函式 printf() 後方僅有一個 • 反組譯 BitCode 字串參數,前端預設將其 字串參數,前端預設將其 轉換為 puts() $ llvm­dis < hello.bc 轉換為 puts()   ; ModuleID = '<stdin>'   ; ModuleID = '<stdin>'   target datalayout = "e­p:32:32:32­...   target datalayout = "e­p:32:32:32­...   target triple = "i386­pc­linux­gnu"   target triple = "i386­pc­linux­gnu"   @str = internal constant [13 x i8] c"Hello world!00"   @str = internal constant [13 x i8] c"Hello world!00"   define i32 @main(i32 %argc, i8** nocapture %argv) nounwind {   define i32 @main(i32 %argc, i8** nocapture %argv) nounwind {   entry:   entry:     %puts = tail call i32 @puts(i8* getelementptr inbounds ([13 x i8]* @str, i32 0, i32 0))     %puts = tail call i32 @puts(i8* getelementptr inbounds ([13 x i8]* @str, i32 0, i32 0))     ret i32 0     ret i32 0   }   }   Declare i32 @puts(i8* nocapture) nounwind   Declare i32 @puts(i8* nocapture) nounwind • 輸出 x86 後端組合語言 $ llc hello.bc ­o hello.s
  • 24.
    LLVM 給予無限可能 C/C++/ libClang AST Obj-C BitCode LibLLVM Optimizer BitCode Arch.td libLLVM xxx.s CodeGenerator
  • 25.
    提供 IDE 的模組化 有了 AST 後,即可針對 靜態編譯解析器 可用許多程式語言 語言特性,做出特定的應用 撰寫 BitCode 生成 器 ( 前端編譯器 ) C/C++/ libClang ,如 PerlObj-C module AST BitCode 其他語言 系統優化處理 LibLLVM Optimizer 作為其他語言的 Source-to-source 特定的後端架構。 轉換器 可以是硬體或軟體 其他語言 BitCode Arch.td LibLLVM xxx.s CodeGenerator 可增添其他模組,如 Polyhedral optimization 針對後端硬體的 Selection DAG
  • 26.
    Xcode OpenCL Compiler OpenCL → Haskell → Clay → C/C++/ libClang AST Obj-C Crack → StrengthReduction BitCode Profile-gen/use 其他語言 AliasAnalysis LibLLVM Optimizer → JavaScript FPGA; → Java ByteCode GPGPU 其他語言 BitCode → CLI → PTX Arch.td LibLLVM regaloc=Pazzle|Graph xxx.s CodeGenerator ObjectCodeEmitter Polly
  • 27.
    整合 PHP 到LLVM 架構
  • 28.
    Zend VM 概況(1) • 依循傳統 SDT (Syntax- Directed Translation) 編譯器 設計方法建構 • 解譯 bytecode • 欠缺進階的編譯器優化機制
  • 29.
    Zend VM 概況(2) • PHP bytecode 使用單純 的表示法,無強制的標準 • 部份資訊如 class 定義, 並未包含在 bytecode
  • 30.
    Zend VM 概況(3)   <?php   <?php   if (1 > 2)   if (1 > 2)         $a = 2 * 3;         $a = 2 * 3;   else   else         $a = 2 * 4;         $a = 2 * 4;   echo $a;   echo $a;   ?>   ?>
  • 31.
    Zend + LLVM op_block: op_block: %execute_data = call @phpllvm_get_execute_data(%1) %execute_data = call @phpllvm_get_execute_data(%1) %execute_result = call @ZEND_IS_SMALLER_HANDLER(%execute_data) %execute_result = call @ZEND_IS_SMALLER_HANDLER(%execute_data) switch i32 %execute_result, label %op_block1 [[ switch i32 %execute_result, label %op_block1 i32 1, label %pre_vm_return i32 1, label %pre_vm_return i32 2, label %pre_vm_enter i32 2, label %pre_vm_enter i32 3, label %pre_vm_leave i32 3, label %pre_vm_leave ]]   <?php   <?php   if (1 > 2)   if (1 > 2)         $a = 2 * 3;         $a = 2 * 3;   else   else         $a = 2 * 4;         $a = 2 * 4;   echo $a;   echo $a;   ?>   ?>
  • 32.
    PHP + LLVM •PECL::LLVM → Zend bytecode to LLVM assembly compiler, unmaintained http://pecl.php.net/package/llvm Compiles Zend bytecode to LLVM assembly and then into optimized machine code. • Roadsend PHP / Raven • Static analyzer which dumps (in XML) • Tokens / AST / Generated IR • Various analysis passes • Port of phc optimizer passes
  • 33.
    PHP + LLVM •HipHop for PHP 僅能執行小部份的 PHP 程 式,而且無法有效佈署 (deployment; 輸出 為 POSIX C++ code) • PHP 不該侷限於伺服器端的應用 • 開發工具的整合 • 透過 LLVM 的 Polly 與 LTO (Link-Time Optimization) ,可進一步優化 Zend bytecode → LLVM bitcode 的執行 • memcache / MP / GPGPU
  • 34.
    架構於 LLVM 的程式語言實做(1) • Unladen Swallow (Google): faster Python $ ./perf.py -r -b call_simple --args "-j always," ../q2/python ../q3/python • Min: 1.618273 -> 0.908331: 78.16% faster • Avg: 1.632256 -> 0.924890: 76.48% faster http://code.google.com/p/unladen-swallow • GHC/Haskell's LLVM codegen • 3x faster in some cases http://donsbot.wordpress.com/2010/02/21/ smoking-fast-haskell-code-using-ghcs-new-llvm-codegen/ • LLVM-Lua : JIT/static Lua compiler • http://code.google.com/p/llvm-lua/ 34
  • 35.
    架構於 LLVM 的程式語言實做(2) • IcedTea Version of Sun's OpenJDK (RedHat) • Zero: processor-independent layer that allows OpenJDK to build and run using any processor • Shark: Zero's JIT compiler: uses LLVM to provide native code generation without introducing processor-dependent code. http://icedtea.classpath.org • Emscripten • LLVM-to-JavaScript compiler • It takes LLVM bitcode and compiles that into JavaScript, which can be run on the web (or anywhere else JavaScript can run). http://code.google.com/p/emscripten/ 35
  • 36.