rfc:jit
Differences
This shows you the differences between two versions of the page.
Next revision | Previous revisionLast revisionBoth sides next revision | ||
rfc:jit [2019/01/28 12:33] – created dmitry | rfc:jit [2019/04/12 07:38] – old revision restored (2019/04/01 07:45) laruence | ||
---|---|---|---|
Line 1: | Line 1: | ||
====== PHP RFC: JIT ====== | ====== PHP RFC: JIT ====== | ||
- | * Version: | + | * Version: |
* Date: 2019-01-28 | * Date: 2019-01-28 | ||
- | * Author: Dmitry Stogov, dmitry@zend.com | + | * Author: Dmitry Stogov |
- | * Status: | + | * Status: Accepted |
* First Published at: https:// | * First Published at: https:// | ||
===== Introduction ===== | ===== Introduction ===== | ||
- | It' | + | It' |
+ | |||
+ | ===== The Case for JIT Today ==== | ||
+ | |||
+ | Even though most of the fundamentals for JIT-enabling PHP haven' | ||
+ | |||
+ | First, we believe we've reached the extent of our ability to improve PHP' | ||
+ | |||
+ | Secondly - using JIT may open the door for PHP being more frequently used in other, non-Web, CPU-intensive scenarios - where the performance benefits will actually be very substantial - and for which PHP is probably not even being considered today. | ||
+ | |||
+ | Lastly - making JIT available | ||
===== Proposal ===== | ===== Proposal ===== | ||
- | I propose to include JIT into PHP-8 and provide additional efforts to increase its performance and usability. | + | We propose to include JIT in PHP 8 and provide additional efforts to increase its performance and usability. |
+ | |||
+ | In addition, we propose to consider including JIT in PHP 7.4 as an experimental feature (disabled by default). | ||
- | In addition, I propose to include | + | PHP JIT is implemented as an almost independent part of OPcache. It may be enabled/ |
+ | When enabled, native code of PHP files is stored in an additional region of the OPcache shared memory and op_array-> | ||
- | PHP JIT is implemented as almost independent part of opcache. It may be enabled/ | + | We use DynAsm (developed for LuaJIT project) for generation |
- | Native code of PHP scripts is stored in additional region of opcache shared memory | + | |
- | To generate native code we use DynAsm | + | PHP JIT doesn' |
+ | If type of PHP variable is exactly inferred (in SSA) to LONG or DOUBLE, and it can't be accessed indirectly, JIT may store its value directly in CPU registers, avoiding memory stores and loads. PHP JIT liner-scan register allocation algorithm, tat combines high speed with reasonable quality. | ||
- | The quality of the JIT may be demonstrated on Mondelbrot | + | The quality of the JIT may be demonstrated on Mandelbrot |
<code php> | <code php> | ||
Line 46: | Line 59: | ||
</ | </ | ||
- | Following | + | The following |
<code asm> | <code asm> | ||
Line 251: | Line 264: | ||
jmp .L10 | jmp .L10 | ||
</ | </ | ||
+ | |||
+ | In comparison to V8, HHVM, PyPy and most others modern JIT implementations PHP JIT is extremely simple, but anyway it increases the level of the whole PHP complexity, risk of new kind of bugs and cost of development and maintenance. | ||
===== Backward Incompatible Changes ===== | ===== Backward Incompatible Changes ===== | ||
Line 256: | Line 271: | ||
===== Proposed PHP Version(s) ===== | ===== Proposed PHP Version(s) ===== | ||
- | PHP-8 and PHP-7.4 (separate votes) | + | PHP 8 and PHP 7.4 (separate votes) |
===== RFC Impact ===== | ===== RFC Impact ===== | ||
Line 263: | Line 278: | ||
==== To Existing Extensions ==== | ==== To Existing Extensions ==== | ||
- | none | + | JIT is going to affect third party debuggers (e.g. xdebug) and profilers (e.g. XHProf, Blackfire, Tideways). |
+ | |||
+ | For debugging a particular request, it's possible to disable JIT (together with opcache) changing " | ||
+ | |||
+ | Run-time profiling should work even with JIT-ed code, but this might require development of additional tracing API and corresponding JIT extension, to generate tracing callbacks. | ||
==== To Opcache ==== | ==== To Opcache ==== | ||
- | JIT is implemented as a part of opcache. | + | JIT would be implemented as a part of OPcache. |
==== New Constants ==== | ==== New Constants ==== | ||
Line 273: | Line 292: | ||
==== php.ini Defaults ==== | ==== php.ini Defaults ==== | ||
If there are any php.ini settings then list: | If there are any php.ini settings then list: | ||
- | * opcache.jit_buffer_size - size (in megabytes) | + | * opcache.jit_buffer_size - size of shared memory buffer reserved for native code generation |
- | * opcache.jit - JIT control options. | + | * opcache.jit - JIT control options. |
- | * O - optimization | + | * O - Optimization |
* 0 - don't JIT | * 0 - don't JIT | ||
* 1 - minimal JIT (call standard VM handlers) | * 1 - minimal JIT (call standard VM handlers) | ||
Line 295: | Line 314: | ||
* 0 - none | * 0 - none | ||
* 1 - enable AVX instruction generation | * 1 - enable AVX instruction generation | ||
- | * opcache.jit_debug - JIT debug control options, where each bit enables | + | * opcache.jit_debug - JIT debug control options, where each bit enabling |
- | * (1<< | + | * (1<< |
* (1<< | * (1<< | ||
* (1<< | * (1<< | ||
- | * (1<<4) - allow debugging JIT-ed | + | * (1<<3) - print stubs assembler |
- | * (1<<5) - generate perf.map file to list JIt-ed functions in Linux perf report | + | * (1<<4) - generate perf.map file to list JIt-ed functions in Linux perf report |
+ | * (1<< | ||
* (1<< | * (1<< | ||
* (1<< | * (1<< | ||
- | * (1<< | + | * (1<< |
==== Performance ==== | ==== Performance ==== | ||
- | JIT makes bench.php more than two times faster: 0.140 sec vs 0.320 sec. | + | JIT makes bench.php more than two times faster: 0.140 sec vs 0.320 sec. It is expected to make most CPU-intensive workloads run significantly faster. |
- | However, in current state it doesn' | + | |
- | ===== Open Issues | + | According to Nikita, PHP-Parser became ~1.3 times faster with JIT. Amphp hello-world.php got just 5% speedup. |
- | Make sure there are no open issues | + | |
+ | However, like the previous attempts - it currently doesn' | ||
+ | |||
+ | It's planned to provide additional effort, improving JIT for real-life apps, using profiling and speculative optimizations. | ||
+ | |||
+ | ==== JIT Debugging | ||
+ | As any complication, | ||
+ | |||
+ | In case of crash, we may just run app under gdb until the crash, check that JIT is involved in crash backtrace and find the place: | ||
+ | |||
+ | < | ||
+ | $ gdb php | ||
+ | |||
+ | (gdb) r app.php | ||
+ | |||
+ | ... | ||
+ | |||
+ | (gdb) bt | ||
+ | |||
+ | #1 0xe960dc11 in ?? () | ||
+ | #2 0x08689524 in zend_execute (op_array=0xf4074460, return_value=0x0) at Zend/ | ||
+ | #3 0x085cb93b in zend_execute_scripts (type=8, retval=0x0, file_count=3) at Zend/ | ||
+ | #4 0x0855a890 in php_execute_script (primary_file=0xffffcbfc) at main/ | ||
+ | #5 0x0868ba25 in do_cli (argc=2, argv=0x9035820) at sapi/ | ||
+ | #6 0x0868c65b in main (argc=2, argv=0x9035820) at sapi/ | ||
+ | </ | ||
+ | |||
+ | Unknown function "??" | ||
+ | |||
+ | < | ||
+ | (gdb) p (char*)executor_global.current_execute_data.func.op_array.filename.val | ||
+ | (gdb) p executor_global.current_execute_data.opline.lineno | ||
+ | </ | ||
+ | |||
+ | Line number may be inaccurate, because JIT doesn' | ||
+ | We may disassemble the code around the bogus instruction to understand the real " | ||
+ | |||
+ | < | ||
+ | (gdb) disassemble 0xe960dc00, | ||
+ | </ | ||
+ | |||
+ | Also, it may be useful to analyse bytecode and assembler dump of the bogus JIT-ed function. | ||
+ | |||
+ | < | ||
+ | $ php --opcache.jit_debug=1 app.php | ||
+ | $ php --opcache.jit_debug=2 app.php | ||
+ | </ | ||
+ | |||
+ | To catch the mistake, we might need to trace the JIT code generator (when it generates | ||
+ | |||
+ | PHP JIT may use GDB API to provide information about generated code to debugger. However, it works only for reasonable small scripts. In case of big amount of JIT-ed code, GDB just stuck registering functions. In case we can isolate the bogus code, we may debug JIT in more comfortable way. | ||
+ | |||
+ | < | ||
+ | $ gdb php | ||
+ | |||
+ | (gdb) r -dopcache.jit_debug=0x100 test.php | ||
+ | ... | ||
+ | |||
+ | (gdb) bt | ||
+ | |||
+ | #1 0xe960dc11 in JIT$foo () at test.php: | ||
+ | #2 0x08689524 in zend_execute (op_array=0xf4074460, | ||
+ | #3 0x085cb93b in zend_execute_scripts (type=8, retval=0x0, file_count=3) at Zend/ | ||
+ | #4 0x0855a890 in php_execute_script (primary_file=0xffffcbfc) at main/ | ||
+ | #5 0x0868ba25 in do_cli (argc=2, argv=0x9035820) at sapi/ | ||
+ | #6 0x0868c65b in main (argc=2, argv=0x9035820) at sapi/ | ||
+ | |||
+ | (gdb) disassemble | ||
+ | ... | ||
+ | (gdb) layout asm | ||
+ | </ | ||
+ | |||
+ | ===== State and compatibility ===== | ||
+ | Currently we support x86 and x86_64 on POSIX platforms (tested on Linux with GCC and LVVM) and Windows (both non-ZTS and ZTS builds). We support " | ||
+ | There are no any restrictions on C compiler and OS any more. | ||
===== Future Scope ===== | ===== Future Scope ===== | ||
- | In PHP-8 we are going to improve JIT and perform optimized code generation after an initial profiling of hot functions. This would allow application of speculative optimizations and generation only the code that is really executed. It's also possible to do deeper integration of JIT with preloading and FFI. | + | In PHP 8 we are going to improve JIT and perform optimized code generation after an initial profiling of hot functions. This would allow application of speculative optimizations and generation only the code that is really executed. It's also possible to do deeper integration of JIT with preloading and FFI, and perhaps a standardized way of developing (and providing) built-in functions that are written in PHP, and not just in C. |
===== Proposed Voting Choices ===== | ===== Proposed Voting Choices ===== | ||
- | This project | + | Support for JIT is more a strategic PHP question. JIT definitely |
- | <doodle title=" | + | This project requires a 2/3+1 majority. Voting opened 2019-03-21 and closes 2019-03-28. |
+ | |||
+ | <doodle title=" | ||
* Yes | * Yes | ||
* No | * No | ||
</ | </ | ||
- | As PHP-7.4 is branched and its engine is not going to be significantly changed, we may also include | + | As PHP 7.4 is already |
- | <doodle title=" | + | In case JIT is not included in PHP-7.4 and PHP-8 introduces language compatibility breaks (it already does), existing applications couldn' |
+ | |||
+ | <doodle title=" | ||
* Yes | * Yes | ||
* No | * No | ||
Line 331: | Line 428: | ||
===== Patches and Tests ===== | ===== Patches and Tests ===== | ||
- | https:// | + | - [[https:// |
+ | - https:// | ||
+ | - https:// | ||
===== Implementation ===== | ===== Implementation ===== | ||
- | After the project is implemented, | + | Merged |
- | - the version(s) it was merged | + | |
- | | + | |
- | - a link to the PHP manual entry for the feature | + | |
- | - a link to the language specification section (if any) | + | |
===== References ===== | ===== References ===== | ||
- [[https:// | - [[https:// | ||
- [[https:// | - [[https:// | ||
- | |||
- | ===== Rejected Features ===== | ||
- | Keep this updated with features that were discussed on the mail lists. | ||
rfc/jit.txt · Last modified: 2020/08/01 23:41 by carusogabriel