PHP7 will be officially released in December 2015.##PHP7 will be a PHP script A major version update of the language will also bring significant performance improvements and new features, as well as improve some outdated functions.This release will focus on performance enhancements derived from the phpng branch in the PHP version tree. At the Silicon Valley company's ZendCon conference, PHP tool maker Zend Technologies officially discussed the progress of phpng and PHP7. "(This upgrade) is really focused on helping the industry significantly enhance the execution speed of applications, coupled with the other improvements we have in PHP," said Zend CEO Andy Termans, who was involved in the development of the PHP language. Continuous development and development) expressed.
# # Let’s take a look at the php7 engine and features given on the official website:
PHP7 Engine (What will be in PHP 7 / PHPNG)
1) PHP7 is twice as fast as PHP5.6
##
2) JIT - Just in Time compiler
Just In Time It is a software optimization technology that compiles bytecode into machine code at runtime. From an intuitive point of view, it is easy for us to think that machine code can be directly recognized and executed by computers, and it is more efficient than Zend to read opcode and execute it one by one. Among them, HHVM (HipHop Virtual Machine, HHVM is a Facebook open source PHP virtual machine) uses JIT, which improves their PHP performance test by an order of magnitude and releases shocking test results, which also makes us intuitively think that JIT is A powerful technology that turns stone into gold.
In fact, in 2013, Brother Niao and Dmitry (one of the PHP language core developers) once made a JIT attempt on the PHP5.5 version (it was not released). The original execution process of PHP5.5 is to compile the PHP code into opcode bytecode through lexical and syntactic analysis (the format is somewhat similar to assembly). Then, the Zend engine reads these opcode instructions and parses and executes them one by one.
And they introduced type inference (TypeInf) after the opcode link, then generated ByteCodes through JIT, and then executed.
As a result, exciting results were obtained in the benchmark (test program). After implementing JIT, the performance was improved by 8 times compared with PHP5.5. However, when they put this optimization into the actual project WordPress (an open source blogging project), they saw almost no performance improvement and got a puzzling test result.
So, they used the profile type tool under Linux to analyze the CPU time consumption of program execution.
Distribution of CPU consumption when executing WordPress 100 times:
Notes:21% of CPU time is spent on memory management.
12% of CPU time is spent on hash table operations, mainly adding, deleting, modifying and checking PHP arrays.
30% of CPU time is spent in built-in functions, such as strlen.
25% of CPU time is spent in VM (Zend Engine).
After analysis, two conclusions were drawn:
(1) If the ByteCodes generated by JIT are too large , will cause the CPU cache hit rate to decrease (CPU Cache Miss)
In the PHP5.5 code, because there is no obvious type definition, type inference can only be relied on. Define the variable types that can be inferred as much as possible, and then, combined with type inference, remove branch codes that are not of that type and generate directly executable machine code. However, type inference cannot infer all types. In WordPress, less than 30% of the type information that can be inferred is limited, and the branch code that can be reduced is limited. As a result, after JIT, machine code is directly generated, and the generated ByteCodes are too large, eventually causing a significant decrease in CPU cache hits (CPU Cache Miss).
CPU cache hit means that when the CPU reads and executes instructions, if the required data cannot be read in the CPU's first-level cache (L1), it has to Continue to search downwards, all the way to the second-level cache (L2) and third-level cache (L3), and eventually try to find the required instruction data in the memory area, and the read time gap between the memory and the CPU cache can reach 100x level. Therefore, if the ByteCodes are too large and the number of executed instructions is too large, the multi-level cache cannot accommodate so much data, and some instructions will have to be stored in the memory area.
The size of the cache at all levels of the CPU is also limited. The following picture is the configuration information of the Intel i7 920:
Therefore, the decrease in CPU cache hit rate will cause a serious increase in time consumption. On the other hand, the performance improvement brought by JIT is also offset by it. .
Through JIT, the overhead of VM can be reduced. At the same time, through instruction optimization, the development of memory management can be indirectly reduced because the number of memory allocations can be reduced. However, for real WordPress projects, only 25% of the CPU time is spent on the VM, and the main problem and bottleneck is not actually on the VM. Therefore, the JIT optimization plan was not included in the PHP7 features of this version. However, it is likely to be implemented in a later version, which is worth looking forward to.
(2) The improvement effect of JIT performance depends on the actual bottleneck of the project
JIT has a large impact in the benchmark The improvement in magnitude is because the amount of code is relatively small, the final generated ByteCodes are also relatively small, and the main overhead is in the VM. However, there is no obvious performance improvement in the actual WordPress project because the code volume of WordPress is much larger than that of the benchmark. Although JIT reduces the overhead of the VM, it causes a decrease in CPU cache hits and extra memory because the ByteCodes are too large. Overhead, ultimately, there is no improvement.
Different types of projects will have different CPU overhead ratios and will get different results. Performance testing without actual projects is not very representative.
3). Changes in Zval
In fact, the actual storage carrier of various types of variables in PHP is Zval, which is characterized by its tolerance and tolerance. Essentially, it is a structure (struct) implemented in C language. For students who write PHP, you can roughly understand it as something similar to an array.
PHP5's Zval, the memory occupies 24 bytes:
PHP7's Zval, the memory occupies 16 bytes:
Zval dropped from 24 bytes to 16 bytes. Why did it drop? I need to add a little bit of C language foundation here. , to assist students who are not familiar with C to understand. There is a slight difference between struct and union (union). Each member variable of Struct occupies an independent memory space, while the member variables in union share a memory space (that is to say, if one of the member variables is modified, the public space will be After modification, there will be no records of other member variables). Therefore, although there appear to be a lot more member variables, the actual memory space occupied has decreased.
In addition, there are other features that have been significantly changed. Some simple types no longer use references.
Zval structure diagram:
Zval in the picture consists of two 64bits (1 byte = 8bit, bit is "bit"). If the variable If the type is long or bealoon, and the length does not exceed 64 bits, it will be stored directly in value, and there will be no following reference. When the variable type is array, objec, string, etc. that exceeds 64 bits, the value stored is a pointer pointing to the real storage structure address.
For simple variable types, Zval storage becomes very simple and efficient.
Types that do not require references: NULL, Boolean, Long, Double
Types that require references: String, Array, Object, Resource, Reference
4) . The internal type zend_string
Zend_string is the structure that actually stores the string, and the actual content will be stored in val(char , character type), and val is a char array with a length of 1 (convenient for member variable occupancy).
The last member variable of the structure uses a char array instead of using char*. Here is a small optimization trick that can reduce the CPU cache miss.
If you use a char array, when malloc applies for the memory of the above structure, it is applied in the same area, usually the length is sizeof(_zend_string) actual char storage space. However, if you use char*, what is stored in this location is only a pointer, and the actual storage is in another independent memory area.
Comparison of memory allocation using char[1] and char*:
From the perspective of logic implementation, there is actually not much difference between the two, and the effects are very similar. In fact, when these memory blocks are loaded into the CPU, they look very different. Because the former is the same piece of memory allocated continuously together, it can usually be obtained together when the CPU reads it (because it will be in the same level cache). The latter, because it contains data from two memories, when the CPU reads the first memory, it is very likely that the second memory data is not in the same level cache, so the CPU has to search below L2 (secondary cache), or even to The desired second piece of memory data is found in the memory area. This will cause CPU Cache Miss, and the time-consuming difference between the two can be up to 100 times.
#In addition, when copying a string, using reference assignment, zend_string can avoid memory copying.
5). Changes in PHP arrays (HashTable and Zend Array)
in In the process of writing PHP programs, the most frequently used type is arrays. PHP5 arrays are implemented using HashTable. To put it in a rough summary, it is a HashTable that supports doubly linked lists. It not only supports hash mapping to access elements through array keys, but can also traverse array elements by accessing doubly linked lists through foreach.
PHP5 HashTable:
This picture looks very complicated, with various pointers jumping around. When we access the content of an element through the key value , sometimes it takes three pointer jumps to find the right content. The most important point is that the storage of these array elements is scattered in different memory areas. In the same way, when the CPU reads, because they are likely not in the same level cache, the CPU will have to search in the lower-level cache or even the memory area, which will cause the CPU cache hit to decrease, thereby increasing more consumption. hour.
Zend Array of PHP7 (screenshot from PPT):
The new version of the array structure, Very simple and eye-catching. The biggest feature is that the entire array elements and hash mapping table are all connected together and allocated in the same memory. If you are traversing a simple type array of integers, the efficiency will be very fast, because the array elements (Bucket) themselves are continuously allocated in the same memory, and the zval of the array elements will store the integer elements internally. There is also a pointer external link, and all data is stored in the current memory area. Of course, the most important thing is that it can avoid CPU Cache Miss (CPU cache hit rate decrease).
Changes in Zend Array:
(1) The value of the array defaults to zval.
(2) The size of HashTable is reduced from 72 to 56 bytes, a reduction of 22%.
(3) The size of Buckets is reduced from 72 to 32 bytes, a reduction of 50%.
(4) The memory space of the buckets of array elements is allocated together.
(5) The key of the array element (Bucket.key) points to zend_string.
(6) The value of the array element is embedded in the Bucket.
(7) Reduce CPU Cache Miss.
6). Function Calling Convention
PHP7 has been improved The function calling mechanism reduces some instructions and improves execution efficiency by optimizing the parameter transfer process.
PHP5’s function calling mechanism (screenshot from PPT):
In the figure, the instructions send_val and recv parameters in the vm stack are the same. PHP7 reduces the duplication of these two, To achieve the underlying optimization of the function calling mechanism.
The function calling mechanism of PHP7 (screenshot from PPT):
7). Through macro definitions and inline functions (inline), let the compiler complete part of the work in advance
The macro definition of C language will be executed in the preprocessing stage (compilation stage), part of the work is completed in advance, and there is no need to allocate memory when the program is running. It can realize function-like functions, but there is no stack push or pop-up of function calls. Stack overhead, efficiency will be higher. The same is true for inline functions. In the preprocessing stage, the functions in the program are replaced with function bodies. When the actual running program is executed here, there will be no overhead of function calls.
PHP7 has made a lot of optimizations in this regard and put a lot of work that needs to be performed in the running phase into the compilation phase. For example, parameter type judgment (Parameters Parsing), because all involved here are fixed character constants, can be completed in the compilation stage, thereby improving subsequent execution efficiency.
For example, in the figure below, the way to handle the type of passed parameters is optimized from the writing method on the left to the macro writing method on the right.
##Specific examples:
More Errors become catchable Exceptions
PHP7 implements a global throwable interface, the original Exception and some Errors are implemented This interface is used to define the inheritance structure of exceptions in the form of interfaces. As a result, more Errors in PHP7 become catchable Exceptions and are returned to developers. If they are not caught, they are Errors. If they are caught, they become Exceptions that can be handled within the program. These catchable Errors are usually Errors that will not cause fatal harm to the program, such as a function that does not exist. PHP7 further facilitates developers' processing and gives developers greater control over the program. Because by default, Error will directly cause the program to interrupt, and PHP7 provides the ability to capture and process it, allowing the program to continue executing, providing programmers with more flexible choices.
#For example, to execute a function that we are not sure exists or not, the PHP5-compatible method is to append the judgment function_exist before the function is called, while PHP7 supports capture How to handle Exception.
The example in the picture below
AST (Abstract Syntax Tree, abstract syntax tree)
AST plays the role of a middleware in the PHP compilation process, replacing the original method of spitting out opcode directly from the interpreter, decoupling the interpreter (parser) and the compiler (compliler). It can reduce some Hack code, and at the same time, make the implementation easier to understand and maintain.
PHP5:
PHP7:
More AST information: https://wiki.php.net/rfc/abstract_syntax_tree
##Native TLS (Native Thread local storage, native Thread local storage)#
PHP needs to solve the problem of "thread safety" (TS, Thread Safe) in multi-threaded mode (for example, the woker and event modes of the web server Apache, which are multi-threaded), because threads share the memory space of the process. , so each thread itself needs to build a private space in some way to save its own private data to avoid mutual contamination with other threads. The method adopted by PHP5 is to maintain a large global array and allocate an independent storage space to each thread. Threads access this global data group through their own key values.
This unique key value needs to be passed to every function that needs to use global variables in PHP5. PHP7 believes that this method of passing is not friendly and has some problems. Therefore, try to use a global thread-specific variable to save this key value.
Related Native TLS issues: https://wiki.php.net/rfc/native-tls
##Combined comparison Operator (< ;=>) Combined with comparison operator (<=>)
// PHP 7之前的写法:比较两个数的大小 function order_func($a, $b) { return ($a < $b) ? -1 : (($a > $b) ? 1 : 0); } // PHP新增的操作符 <=>,perfect function order_func($a, $b) { return $a <=> $b; }
Return Type Declarations return type declaration and Scalar Type Declarations scalar type declaration
If combined with the forced type switch command, it can become like this:
If strict_type is not turned on, PHP will try to help you convert it to the required type. After turning it on, PHP will no longer perform type conversion. If the type does not match, it will Throw an error. This is great news for students who like "strongly typed" languages.
More detailed introduction: https://wiki.php.net/rfc/scalar_type_hints_v5PHP7 scalar type declaration RFC
There are several reasons of why we shouldn't reuse version 6 for the next major version of PHP.
cli
cgi
fpm
apache (FastCGI and FPM might be significantly faster if mod_php is built as PIC)
apache2handler
bcmath
bz2
calendar
com_dotnet
ctype
curl
date
dba
dom
enchant
ereg
exif
fileinfo
filter
ftp
gd
gettext
gmp
hash
iconv
imap
intl
json
ldap
libxml
mbstring
mcrypt
mysql
mysqli
mysqlnd
odbc (tested with unixODBC and MySQL driver)
openssl
OPcache
pcntl
pcre
PDO
pdo_firebird
pdo_mysql
PDO_ODBC (tested with unixODBC and MySQL driver)
pdo_pgsql
pdo_sqlite
pgsql
Phar
posix
pspell
readline
recode
Reflection
session
shmop
SimpleXML
snmp
soap
sockets
SPL
sqlite3
standard
sysvmsg
sysvsem
sysvshm
tidy
tokenizer
wddx
xml
xmlreader
xmlwriter
PHP7 VS PHP5.6
1. Opcache
Remember to enable Zend Opcache, Because PHP7 is faster than PHP-5.6 with Opcache enabled even without Opcache enabled, some people did not enable Opcache during the previous testing period. Enabling Opcache is very simple, just add:
##zend_extension=opcache.so# in the php.ini configuration file
##opcache.enable=1opcache.enable_cli=1"
2. Use a new compiler
##Use a newer compiler, GCC 4.8 is recommended Above, because only PHP with GCC 4.8 or above will enable Global Register for opline and execute_data support, this will bring about a 5% performance improvement (measured from the QPS perspective of Wordpres)
In fact, versions before GCC 4.8 also support it, but we found that there are bugs in its support, so this feature must be enabled in version 4.8 or above.
##3. HugePage
Take my CentOS 6.5 as an example, through:
$sudo sysctl vm.nr_hugepages=512
##Allocate 512 reserved huge page memory:
$ cat /proc/meminfo | grep Huge
AnonHugePages: 106496 kB
HugePages_Total: 512
HugePages_Free: 504
##HugePages_Rsvd: 27
HugePages_Surp: 0
Hugepagesize: 2048 kB
##Then in php .ini added:
In this way, PHP will use large memory pages to save its own text segment and huge in memory allocation, reducing TLB misses and thereby improving performance.
4. Opcache file cache
Open Opcache File Cache (experimental), by turning this on, we can let Opcache cache the opcode cache in an external file. For some scripts, there will be a significant performance improvement.
Add in php.ini:
##opcache.file_cache=/tmp
In this way, PHP will cache some Opcode binary export files in the /tmp directory, which can exist across the PHP life cycle.
5、PGO
##My previous articles: Make your PHP7 faster (GCC PGO) has also been introduced. If your PHP is specifically for one project, such as just for your WordPress, or Drupal, or something else, then you can try to improve PHP through PGO. , specially designed to improve performance for your project.
Specifically, WordPress 4.1 is used as the optimization scenario. First when compiling PHP:
$ make prof-gen
##
Then train PHP with your project, for example for WordPress:
##$ sapi/cgi/php-cgi -T 100 /home/huixinchen/local/www/htdocs/wordpress/index.php >/dev/null
also Just let php-cgi run the WordPress homepage 100 times to generate some profile information in the process.
at last:
$ make prof-clean
$ make prof-use
The PHP7 you compile at this time is tailor-made for your project Built for the highest performance compiled version.
That’s all for now. I’ll add more when I think of it later. Everyone is welcome to try it, thanks.
The above is the detailed content of Detailed explanation of the new features of PHP7 What will be in PHP 7. For more information, please follow other related articles on the PHP Chinese website!