PHP7新特性

PHP7php

2015.12.3 发生了两件大事, PHP7 问世了, Swift 开源了。python

最好的语言发布了新的版本,一个划时代的大版本: PHP7 。mysql

PHP7 修复了大量 BUG ,新增了功能和语法糖。这些改动涉及到了核心包、 GD 库、 PDO 、 ZIP 、 ZLIB 等熟悉和不熟悉的核心功能与扩展包。web

PHP7 移除了已经被废弃的函数,如 mysql_ 系列函数在 PHP5.5 被废弃,在 PHP7 被删除。sql

PHP7 的性能高于 HHVM 。而且是 PHP5.6 的两倍。swift

http://php.net/archive/2015.php#id2015-12-03-1数组

2015 年 12 月 3 号缓存

PHP 开发团队宣布 PHP 7.0.0 即将上市。本次发布标志着新的重要的 PHP 7 系列的开始。安全

PHP 7.0.0 附带了一个新版本的 Zend 引擎中,无数的改进和新功能,如php7

性能改善:

PHP 7 高达两倍快的 PHP 5.6

显著减小内存使用

抽象语法树

一致的 64 位支持

改进的异常层次结构

许多转化为异常致命错误

安全随机数发生器

删除旧的和不支持的 SAPIs 和扩展

空合并运算符(?)

返回和标量类型声明

匿名类

零成本断言

这是下一个主要版本的 PHP 。它的发布是近两年的发展征程的结果。这是核心团队的一个很是特殊的成就。并且,它是许多活跃的社区成员难以置信努力的结果。事实上,这是一个新的 PHP 一代的崛起与巨大潜力。

恭喜你们,这是一个壮观的 PHP 的世界!


1.PHP7速度是 PHP5.6 的两倍


2.JIT - Just in Time compiler (即时编辑器)
Just In Time(即时编译)是一种软件优化技术,指在运行时才会去编译字节码为机器码。从直觉出发,咱们都很容易认为,机器码是计算机可以直接识别和执行的,比起Zend读取opcode逐条执行效率会更高。其中,HHVM(HipHop Virtual Machine,HHVM是一个Facebook开源的PHP虚拟机)就采用JIT,让他们的PHP性能测试提高了一个数量级,放出一个使人震惊的测试结果,也让咱们直观地认为JIT是一项点石成金的强大技术。

而实际上,在2013年的时候,鸟哥和Dmitry(PHP语言内核开发者之一)就曾经在PHP5.5的版本上作过一个JIT的尝试(并无发布)。PHP5.5的原来的执行流程,是将PHP代码经过词法和语法分析,编译成opcode字节码(格式和汇编有点像),而后,Zend引擎读取这些opcode指令,逐条解析执行。

而他们在opcode环节后引入了类型推断(TypeInf),而后经过JIT生成ByteCodes,而后再执行。


3.Zval的改变

PHP的各类类型的变量,其实,真正存储的载体就是Zval,它特色是海纳百川,有容乃大。从本质上看,它是C语言实现的一个结构体(struct)。对于写PHP的同窗,能够将它粗略理解为是一个相似array数组的东西。

PHP5的Zval,内存占据24个字节:
PHP7的Zval,内存占据16个字节:

Zval从24个字节降低到16个字节,为何会降低呢,这里须要补一点点的C语言基础,辅助不熟悉C的同窗理解。struct和union(联合体)有点不一样,Struct的每个成员变量要各自占据一块独立的内存空间,而union里的成员变量是共用一块内存空间(也就是说修改其中一个成员变量,公有空间就被修改了,其余成员变量的记录也就没有了)。所以,虽然成员变量看起来多了很多,可是实际占据的内存空间却降低了。

除此以外,还有被明显改变的特性,部分简单类型再也不使用引用。


4.内部类型zend_string

Zend_string是实际存储字符串的结构体,实际的内容会存储在val(char,字符型)中,而val是一个char数组,长度为1(方便成员变量占位)。

结构体最后一个成员变量采用char数组,而不是使用char*,这里有一个小优化技巧,能够下降CPU的cache miss。

若是使用char数组,当malloc申请上述结构体内存,是申请在同一片区域的,一般是长度是sizeof(_zend_string) + 实际char存储空间。可是,若是使用char*,那个这个位置存储的只是一个指针,真实的存储又在另一片独立的内存区域内。

从逻辑实现的角度来看,二者其实也没有多大区别,效果很相似。而实际上,当这些内存块被载入到CPU的中,就显得很是不同。前者由于是连续分配在一块儿的同一块内存,在CPU读取时,一般均可以一同得到(由于会在同一级缓存中)。然后者,由于是两块内存的数据,CPU读取第一块内存的时候,极可能第二块内存数据不在同一级缓存中,使CPU不得不往L2(二级缓存)如下寻找,甚至到内存区域查到想要的第二块内存数据。这里就会引发CPU Cache Miss,而二者的耗时最高能够相差100倍。

另外,在字符串复制的时候,采用引用赋值,zend_string能够避免的内存拷贝。


5.PHP数组的变化(HashTable和Zend Array)

在编写PHP程序过程当中,使用最频繁的类型莫过于数组,PHP5的数组采用HashTable实现。若是用比较粗略的归纳方式来讲,它算是一个支持双向链表的HashTable,不只支持经过数组的key来作hash映射访问元素,也能经过foreach以访问双向链表的方式遍历数组元素。

这个图看起来很复杂,各类指针跳来跳去,当咱们经过key值访问一个元素内容的时候,有时须要3次的指针跳跃才能找对须要的内容。而最重要的一点,就在于这些数组元素存储,都是分散在各个不一样的内存区域的。同理可得,在CPU读取的时候,由于它们就极可能不在同一级缓存中,会致使CPU不得不到下级缓存甚至内存区域查找,也就是引发CPU缓存命中降低,进而增长更多的耗时。

新版本的数组结构,很是简洁,让人眼前一亮。最大的特色是,整块的数组元素和hash映射表所有链接在一块儿,被分配在同一块内存内。若是是遍历一个整型的简单类型数组,效率会很是快,由于,数组元素(Bucket)自己是连续分配在同一块内存里,而且,数组元素的zval会把整型元素存储在内部,也再也不有指针外链,所有数据都存储在当前内存区域内。固然,最重要的是,它可以避免CPU Cache Miss(CPU缓存命中率降低)。


6.函数调用机制(Function Calling Convention)
PHP7改进了函数的调用机制,经过优化参数传递的环节,减小了一些指令,提升执行效率。


7.经过宏定义和内联函数(inline),让编译器提早完成部分工做
C语言的宏定义会被在预处理阶段(编译阶段)执行,提早将部分工做完成,无需在程序运行时分配内存,可以实现相似函数的功能,却没有函数调用的压栈、弹栈开销,效率会比较高。内联函数也相似,在预处理阶段,将程序中的函数替换为函数体,真实运行的程序执行到这里,就不会产生函数调用的开销。

PHP7在这方面作了很多的优化,将很多须要在运行阶段要执行的工做,放到了编译阶段。例如参数类型的判断(Parameters Parsing),由于这里涉及的都是固定的字符常量,所以,能够放到到编译阶段来完成,进而提高后续的执行效率。

PHP7新特性 What will be in PHP 7/PHPNG
http://blog.csdn.net/hguisu/article/details/45094079

 


PHP7的一些新特性

1. 运算符(NULL 合并运算符)

把这个放在第一个说是由于我以为它颇有用。用法:

$a = $_GET['a'] ?? 1;

它至关于:

<php
$a = isset($_GET['a']) ? $_GET['a'] : 1;

咱们知道三元运算符是能够这样用的:

$a ?: 1

可是这是创建在 $a 已经定义了的前提上。新增的 ?? 运算符能够简化判断。

 

2. 函数返回值类型声明

官方文档提供的例子(注意 … 的边长参数语法在 PHP 5.6 以上的版本中才有):

<php
function arraysSum(array ...$arrays): array
{
return array_map(function(array $array): int {
return array_sum($array);
}, $arrays);
}

print_r(arraysSum([1,2,3], [4,5,6], [7,8,9]));
从这个例子中能够看出如今函数(包括匿名函数)均可以指定返回值的类型。

这种声明的写法有些相似于 swift:

func sayHello(personName: String) -> String {
let greeting = "Hello, " + personName + "!"
return greeting
}
这个特性能够帮助咱们避免一些 PHP 的隐式类型转换带来的问题。在定义一个函数以前就想好预期的结果能够避免一些没必要要的错误。

不过这里也有一个特色须要注意。PHP 7 增长了一个 declare 指令:strict_types,既使用严格模式。

使用返回值类型声明时,若是没有声明为严格模式,若是返回值不是预期的类型,PHP 仍是会对其进行强制类型转换。可是若是是严格模式, 则会出发一个 TypeError 的 Fatal error。

强制模式:

<php
function foo($a) : int
{
return $a;
}

foo(1.0);
以上代码能够正常执行,foo 函数返回 int 1,没有任何错误。

严格模式:

<php
declare(strict_types=1);

function foo($a) : int
{
return $a;
}

foo(1.0);
# PHP Fatal error: Uncaught TypeError: Return value of foo() must be of the type integer, float returned in test.php:6
在声明以后,就会触发致命错误。

是否是有点相似与 js 的 strict mode?

 

3. 标量类型声明

PHP 7 中的函数的形参类型声明能够是标量了。在 PHP 5 中只能是类名、接口、array 或者 callable (PHP 5.4,便可以是函数,包括匿名函数),如今也可使用 string、int、float和 bool 了。

官方示例:

<php
// Coercive mode
function sumOfInts(int ...$ints)
{
return array_sum($ints);
}

var_dump(sumOfInts(2, '3', 4.1));
须要注意的是上文提到的严格模式的问题在这里一样适用:强制模式(默认,既强制类型转换)下仍是会对不符合预期的参数进行强制类型转换,严格模式下则触发 TypeError 的致命错误。

 

4. use 批量声明

PHP 7 中 use 能够在一句话中声明多个类或函数或 const 了:

<php
use some/namespace/{ClassA, ClassB, ClassC as C};
use function some/namespace/{fn_a, fn_b, fn_c};
use const some/namespace/{ConstA, ConstB, ConstC};
但仍是要写出每一个类或函数或 const 的名称(并无像 python 同样的 from some import * 的方法)。

须要留意的问题是:若是你使用的是基于 composer 和 PSR-4 的框架,这种写法是否能成功的加载类文件?实际上是能够的,composer 注册的自动加载方法是在类被调用的时候根据类的命名空间去查找位置,这种写法对其没有影响。

 

5. 其余的特性

其余的一些特性我就不一一介绍了,有兴趣能够查看官方文档:http://php.net/manual/en/migration70.new-features.php

简要说几个:

PHP 5.3 开始有了匿名函数,如今又有了匿名类了;

define 如今能够定义常量数组;

闭包( Closure)增长了一个 call 方法;

生成器(或者叫迭代器更合适)能够有一个最终返回值(return),也能够经过 yield from 的新语法进入一个另一个生成器中(生成器委托)。

生成器的两个新特性(return 和 yield from)能够组合。具体的表象你们能够自行测试。PHP 7 如今已经到 RC5 了,最终的版本应该会很快到来。

 

延伸阅读:
http://www.baidu.com/s?wd=php7%20新特性
http://www.sogou.com/web?query=php7%20新特性
https://www.so.com/s?q=php7新特性

http://developer.51cto.com/art/201510/494674.htm

http://www.tuicool.com/articles/yARJRjQ

相关文章
相关标签/搜索