PHP 性能分析10则

下面咱们根据小程序来验证一些常见的性能差异。php

 

2.一、使用 echo 仍是 print前端

 

在有的建议规则中,会建议使用 echo ,而不使用 print。说 print 是函数,而 echo 是语法结构。实际上并非如此,print 也是语法结构,相似的语法结构,还有多个,好比 list、isset、require 等。不过对于 PHP 7 如下 PHP 版本而言,二者确实有性能上的差异。以下两份代码:程序员

 

for($i=0; $i<1000000; $i++)
{
echo("Hello,World!");
}

for($i=0; $i<1000000; $i++)
{
print ("Hello,World!");
}

在 PHP 5.3 中运行速度分别以下(各2次):web

 

[root@localhostphpperf]# time php echo1.php > /dev/null正则表达式

 

real 0m0.233s 算法

user 0m0.153s 小程序

sys 0m0.080s 后端

[root@localhostphpperf]# time php echo1.php > /dev/null数组

 

real 0m0.234s 浏览器

user 0m0.159s

sys 0m0.073s

 

[root@localhostphpperf]# time phpecho.php> /dev/null

 

real 0m0.203s

user 0m0.130s

sys 0m0.072s

[root@localhostphpperf]# time phpecho.php> /dev/null

 

real 0m0.203s

user 0m0.128s

sys 0m0.075s

 

在 PHP5.3 版中效率差距10%以上。而在 PHP5.4 以上的版本中,区别不大,以下是 PHP7 中的运行效率。

 

[root@localhostphpperf]# time php7 echo.php> /dev/null

 

real 0m0.151s

user 0m0.088s

sys 0m0.062s

[root@localhostphpperf]# time php7 echo.php> /dev/null

 

real 0m0.145s

user 0m0.084s

sys 0m0.061s

 

[root@localhostphpperf]# time php7 echo1.php > /dev/null

 

real 0m0.140s

user 0m0.075s

sys 0m0.064s

[root@localhostphpperf]# time php7 echo1.php > /dev/null

 

real 0m0.146s

user 0m0.077s

sys 0m0.069s

 

正如浏览器前端的一些优化准则同样,没有啥特别通用的原则,每每根据不一样的状况和版本,规则也会存在不一样。

 

2.二、require 仍是 require_once?

 

在一些常规的优化规则中,会提到,建议使用 require_ once 而不是 require,现由是 require_ once 会去检测是否重复,而 require 则不须要重复检测。

 

在大量不一样文件的包含中,require_ once 略慢于 require。可是 require_ once 的检测是一项内存中的行为,也就是说即便有数个须要加载的文件,检测也只是内存中的比较。而 require 的每次从新加载,都会从文件系统中去读取分析。于是 require_ once 会比 require 更佳。我们也使用一个例子来看一下。

 

str.php

global$str;
$str= "China has a large population";

require.php
for($i=0; $i<100000; $i++) {
require "str.php";
}

require_once.php
for($i=0; $i<100000; $i++) {
require_once"str.php";
}

上面的例子,在 PHP7 中,require_ once.php 的运行速度是 require.php 的30倍!在其余版本也能获得大体相同的结果。

 

[root@localhostphpperf]# time php7 require.php

 

real 0m1.712s

user 0m1.126s

sys 0m0.569s

[root@localhostphpperf]# time php7 require.php

 

real 0m1.640s

user 0m1.113s

sys 0m0.515s

 

[root@localhostphpperf]# time php7 require_once.php

 

real 0m0.066s

user 0m0.063s

sys 0m0.003s

[root@localhostphpperf]# time php7 require_once.php

 

real 0m0.057s

user 0m0.052s

sys 0m0.004s

 

从上能够看到,若是存在大量的重复加载的话,require_ once 明显优于 require,由于重复的文件再也不有 IO 操做。即便不是大量重复的加载,也建议使用 require_ once,由于在一个程序中,通常不会存在数以千百计的文件包含,100次内存比较的速度差距,一个文件包含就至关了。

 

2.三、单引号仍是双引号?

 

单引号,仍是双引号,是一个问题。通常的建议是能使用单引号的地方,就不要使用双引号,由于字符串中的单引号,不会引发解析,从而效率更高。那来看一下实际的差异。

 

classUser
{
private $uid;
private $username;
private $age;

function  __construct($uid, $username,$age){
$this->uid= $uid;
$this->username = $username;
$this->age = $age;
    }
function getUserInfo()
    {
return "UID:".$this->uid." UserName:".$this->username." Age:".$this->age;
    }
function getUserInfoSingle()
    {
return 'UID:'.$this->uid.' UserName:'.$this->username.' Age'.$this->age;
    }

function getUserInfoOnce()
    {
return "UID:{$this->uid}UserName:{$this->username} Age:{$this->age}";
    }

function getUserInfoSingle2()
    {
return 'UID:{$this->uid} UserName:{$this->username} Age:{$this->age}';
    }
}

for($i=0; $i<1000000;$i++) {
$user = new User($i, "name".$i, $i%100);
$user->getUserInfoSingle();
}

在上面的 User 类中,有四个不一样的方法,完成同样的功能,就是拼接信息返回,看看这四个不一样的方法的区别。

 

第一个、getUserInfo ,使用双引号和属性相拼接

 

[root@localhostphpperf]# time php7 string.php

 

real 0m0.670s

user 0m0.665s

sys 0m0.002s

[root@localhostphpperf]# time php7 string.php

 

real 0m0.692s

user 0m0.689s

sys 0m0.002s

[root@localhostphpperf]# time php7 string.php

 

real 0m0.683s

user 0m0.672s

sys 0m0.004s

 

第二个、getUserInfoSingle ,使用单引号和属性相拼接

 

[root@localhostphpperf]# time php7 string.php

 

real 0m0.686s

user 0m0.683s

sys 0m0.001s

[root@localhostphpperf]# time php7 string.php

 

real 0m0.671s

user 0m0.666s

sys 0m0.003s

[root@localhostphpperf]# time php7 string.php

 

real 0m0.669s

user 0m0.666s

sys 0m0.002s

 

可见在拼接中,单双引号并没有明显差异。

 

第三个、getUserInfoOnce,再也不使用句号.链接,而是直接引入在字符串中解析。

 

[root@localhostphpperf]# time php7 string.php

 

real 0m0.564s

user 0m0.556s

sys 0m0.006s

[root@localhostphpperf]# time php7 string.php

 

real 0m0.592s

user 0m0.587s

sys 0m0.004s

[root@localhostphpperf]# time php7 string.php

 

real 0m0.563s

user 0m0.559s

sys 0m0.003s

 

从上面可见,速度提升了0.06s-0.10s,有10%-20%的效率提高。可见连缀效率更低一些。

 

第四个、getUserInfoSingle2 虽然没有达到咱们真正想要的效果,功能是不正确的,可是在字符串中,再也不须要解析变量和获取变量值,因此效率确实有大幅度提高。

 

[root@localhostphpperf]# time php7 string.php

 

real 0m0.379s

user 0m0.375s

sys 0m0.003s

[root@localhostphpperf]# time php7 string.php

 

real 0m0.399s

user 0m0.394s

sys 0m0.003s

[root@localhostphpperf]# time php7 string.php

 

real 0m0.377s

user 0m0.371s

sys 0m0.004s

 

效率确实有了大的提高,快了50%。

 

那么这个快,是因为不须要变量引用解析带来的,仍是只要加入$自然的呢?咱们再试着写了一个方法。

 

functiongetUserInfoSingle3()
{
return "UID:{\$this->uid} UserName:{\$this->username} Age:{\$this->age}";
}

获得以下运行时间:

 

[root@localhostphpperf]# time php7 string.php

 

real 0m0.385s

user 0m0.381s

sys 0m0.002s

[root@localhostphpperf]# time php7 string.php

 

real 0m0.382s

user 0m0.380s

sys 0m0.002s

[root@localhostphpperf]# time php7 string.php

 

real 0m0.386s

user 0m0.380s

sys 0m0.004s

 

发现转义后的字符串,效率跟单引号是一致的,从这里也能够看见,单引号仍是双引号包含,若是不存在须要解析的变量,几乎没有差异。若是有须要解析的变量,你也不能光用单引号,要么使用单引号和连缀,要么使用内部插值,因此在这条规则上,不用太过纠结。

 

2.四、错误应该打开仍是关闭?

 

在 PHP 中,有多种错误消息,错误消息的开启是否会带来性能上的影响呢?从直觉以为,因为错误消息,自己会涉及到 IO 输出,不管是输出到终端或者 error_log,都是如此,因此确定会影响性能。咱们来看看这个影响有多大。

 

error_reporting(E_ERROR);
for($i=0; $i<1000000;$i++) {
$str= "一般,$PHP中的垃圾回收机制,仅仅在循环回收算法确实运行时会有时间消耗上的增长。可是在日常的(更小的)脚本中应根本就没有性能影响。
然而,在日常脚本中有循环回收机制运行的状况下,内存的节省将容许更多这种脚本同时运行在你的服务器上。由于总共使用的内存没达到上限。";
}

在上面的代码中,咱们涉及到一个不存在的变量,因此会报出 Notice 错误:

 

Notice: Undefined variable: PHP 中的垃圾回收机制,仅仅在循环回收算法确实运行时会有时间消耗上的增长。可是在日常的 in xxxx/string2.php on line 10

 

若是把 E_ ERROR 改为 E_ ALL 就能看到大量的上述错误输出。

 

咱们先执行 E_ ERROR 版,这个时候没有任何错误日志输出。获得以下数据:

 

[root@localhostphpperf]# time php7 string2.php

 

real 0m0.442s

user 0m0.434s

sys 0m0.005s

[root@localhostphpperf]# time php7 string2.php

 

real 0m0.487s

user 0m0.484s

sys 0m0.002s

[root@localhostphpperf]# time php7 string2.php

 

real 0m0.476s

user 0m0.471s

sys 0m0.003s

 

再执行 E_ ALL 版,有大量的错误日志输出,咱们把输出重定向到/dev/null

 

[root@localhostphpperf]# time php7 string2.php > /dev/null

 

real 0m0.928s

user 0m0.873s

sys 0m0.051s

[root@localhostphpperf]# time php7 string2.php > /dev/null

 

real 0m0.984s

user 0m0.917s

sys 0m0.064s

[root@localhostphpperf]# time php7 string2.php > /dev/null

 

real 0m0.945s

user 0m0.887s

sys 0m0.056s

 

可见慢了将近一倍。

 

如上可见,即便输出没有正式写入文件,错误级别打开的影响也是巨大的。在线上咱们应该将错误级别调到 E_ ERROR 这个级别,同时将错误写入 error_ log,既减小了没必要要的错误信息输出,又避免泄漏路径等信息,形成安全隐患。

 

2.五、正则表达式和普通字符串操做

 

在字符串操做中,有一条常见的规则,便是能使用普通字符串操做方法替代的,就不要使用正则表达式来处理,用 C 语言操做 PCRE 作过正则表达式处理的童鞋应该清楚,须要先 compile,再 exec,也就是说是一个相对复杂的过程。如今就比较一下二者的差异。

 

对于简单的分隔,咱们可使用 explode 来实现,也可使用正则表达式,好比下面的例子:

 

ini_set("precision", 16);
function microtime_ex()
{
list($usec, $sec) = explode(" ", microtime());
return $sec+$usec;
}

for($i=0; $i<1000000; $i++) {
microtime_ex();
}

耗时在0.93-1S之间。

 

[root@localhostphpperf]# time php7 pregstring.php

 

real 0m0.941s

user 0m0.931s

sys 0m0.007s

[root@localhostphpperf]# time php7 pregstring.php

 

real 0m0.986s

user 0m0.980s

sys 0m0.004s

[root@localhostphpperf]# time php7 pregstring.php

 

real 0m1.004s

user 0m0.998s

sys 0m0.003s

 

咱们再将分隔语句替换成:

 

list($usec, $sec) = preg_split("#\s#", microtime());

获得以下数据,慢了近10-20%。

 

[root@localhostphpperf]# time php7 pregstring1.php

 

real 0m1.195s

user 0m1.182s

sys 0m0.004s

[root@localhostphpperf]# time php7 pregstring1.php

 

real 0m1.222s

user 0m1.217s

sys 0m0.003s

[root@localhostphpperf]# time php7 pregstring1.php

 

real 0m1.101s

user 0m1.091s

sys 0m0.005s

 

再将语句替换成:

 

list($usec, $sec) = preg_split("#\s+#", microtime());

即匹配一到多个空格,并无太多的影响。除了分隔外,查找咱们也来看一个例子。

 

第一段代码:

 

$str= "China has a Large population";
for($i=0; $i<1000000; $i++) {
if(preg_match("#l#i", $str))
    {
    }
}

第二段代码:

 

$str= "China has a large population";
for($i=0; $i<1000000; $i++) {
if(stripos($str, "l")!==false)
    {
    }
}

这两段代码达到的效果相同,都是查找字符串中有无 l 或者 L 字符。

 

在 PHP 7 下运行效果以下:

 

[root@localhostphpperf]# time php7 pregstring2.php

 

real 0m0.172s

user 0m0.167s

sys 0m0.003s

[root@localhostphpperf]# time php7 pregstring2.php

 

real 0m0.199s

user 0m0.196s

sys 0m0.002s

[root@localhostphpperf]# time php7 pregstring3.php

 

real 0m0.185s

user 0m0.182s

sys 0m0.003s

[root@localhostphpperf]# time php7 pregstring3.php

 

real 0m0.184s

user 0m0.181s

sys 0m0.003s

 

二者区别不大。再看看在 PHP5.6 中的表现。

 

[root@localhostphpperf]# time php56 pregstring2.php

 

real 0m0.470s

user 0m0.456s

sys 0m0.004s

[root@localhostphpperf]# time php56 pregstring2.php

 

real 0m0.506s

user 0m0.500s

sys 0m0.005s

[root@localhostphpperf]# time php56 pregstring3.php

 

real 0m0.348s

user 0m0.342s

sys 0m0.004s

[root@localhostphpperf]# time php56 pregstring3.php

 

real 0m0.376s

user 0m0.364s

sys 0m0.003s

 

可见在 PHP 5.6 中表现仍是很是明显的,使用正则表达式慢了20%。PHP7 难道是对已使用过的正则表达式作了缓存?咱们调整一下代码以下:

 

$str= "China has a Large population";

for($i=0; $i<1000000; $i++) {
$pattern = "#".chr(ord('a')+$i%26)."#i";
if($ret = preg_match($pattern, $str)!==false)
    {
    }
}

这是一个动态编译的 pattern。

 

$str= "China has a large population";

for($i=0; $i<1000000; $i++) {
$pattern = "".chr(ord('a')+$i%26)."";
if($ret = stripos($str, $pattern)!==false)
    {
    }
}

在 PHP7 中,获得了以下结果:

 

[root@localhostphpperf]# time php7 pregstring2.php

 

real 0m0.351s

user 0m0.346s

sys 0m0.004s

[root@localhostphpperf]# time php7 pregstring2.php

 

real 0m0.359s

user 0m0.352s

sys 0m0.004s

[root@localhostphpperf]# time php7 pregstring3.php

 

real 0m0.375s

user 0m0.369s

sys 0m0.003s

[root@localhostphpperf]# time php7 pregstring3.php

 

real 0m0.370s

user 0m0.365s

sys 0m0.005s

 

可见二者并不明显。而在 PHP 5.6 中,一样的代码:

 

[root@localhostphpperf]# time php56 pregstring2.php

 

real 0m1.022s

user 0m1.015s

sys 0m0.005s

[root@localhostphpperf]# time php56 pregstring2.php

 

real 0m1.049s

user 0m1.041s

sys 0m0.005s

[root@localhostphpperf]# time php56 pregstring3.php

 

real 0m0.923s

user 0m0.821s

sys 0m0.002s

[root@localhostphpperf]# time php56 pregstring3.php

 

real 0m0.838s

user 0m0.831s

sys 0m0.004s

 

在 PHP 5.6 中,stripos 版明显要快于正则表达式版,由上两例可见,PHP7对正则表达式的优化仍是至关惊人的。其次也建议,能用普通字符串操做的地方,能够避免使用正则表达式。由于在其余版本中,这个规则仍是适用的。某 zend 大牛官方的分享给出以下数据:

 

stripos(‘http://’, $website) 速度是preg_match(‘/http:\/\//i’, $website) 的两倍

 

ctype_alnum()速度是preg_match(‘/^\s*$/’)的5倍;

 

“if ($test == (int)$test)”preg_match(‘/^\d*$/’)快5倍

 

能够相见,正则表达式是相对低效的。

 

2.六、数组元素定位查找

 

在数组元素的查找中,有一个关键的注意点就是数组值和键的查找速度,差别很是大。了解过 PHP 扩展开发的朋友,应该清楚,数组在底层实际上是 Hash 表。因此键是以快速定位的,而值却未必。下面来看例子。

 

首先们构造一个数组:

 

$a= array();
for($i=0;$i<100000;$i++){
$a[$i] = $i;
}

在这个数组中,咱们测试查找值和查找键的效率差异。

 

第一种方法用 array_ search,第二种用 array_ key_ exists,第三种用 isset 语法结构。 代码分别以下:

 

//查找值
foreach($a as $i)
{
array_search($i, $a);
}
//查找键
foreach($a as $i)
{
array_key_exists($i, $a);
}
//断定键是否存在
foreach($a as $i)
{
if(isset($a[$i]));
}

运行结果以下:

 

[root@localhostphpperf]# time php7 array.php

 

real 0m9.026s

user 0m8.965s

sys 0m0.007s

[root@localhostphpperf]# time php7 array.php

 

real 0m9.063s

user 0m8.965s

sys 0m0.005s

[root@localhostphpperf]# time php7 array1.php

 

real 0m0.018s

user 0m0.016s

sys 0m0.001s

[root@localhostphpperf]# time php7 array1.php

 

real 0m0.021s

user 0m0.015s

sys 0m0.004s

[root@localhostphpperf]# time php7 array2.php

 

real 0m0.020s

user 0m0.014s

sys 0m0.006s

[root@localhostphpperf]# time php7 array2.php

 

real 0m0.016s

user 0m0.009s

sys 0m0.006s

 

由上例子可见,键值查找的速度比值查找的速度有百倍以上的效率差异。于是若是能用键值定位的地方,尽可能用键值定位,而不是值查找。

 

2.七、对象与数组

 

在 PHP 中,数组就是字典,字典能够存储属性和属性值,并且不管是键仍是值,都不要求数据类型统一,因此对象数据存储,既能用对象数据结构的属性存储数据,也能使用数组的元素存储数据。那么二者有何差异呢?

 

使用对象:

 

classUser
{
public $uid;
public $username;
public $age;
function getUserInfo()
    {
return "UID:".$this->uid." UserName:".$this->username." Age:".$this->age;
    }
}

for($i=0; $i<1000000;$i++) {
$user = new User();
$user->uid= $i;
$user->age = $i%100;
$user->username="User".$i;
$user->getUserInfo();
}

使用数组:

 

functiongetUserInfo($user)
{
return "UID:".$user['uid']." UserName:".$user['username']." Age:".$user['age'];
}

for($i=0; $i<1000000;$i++) {
$user = array("uid"=>$i,"age" =>$i%100,"username"=>"User".$i);
getUserInfo($user);
}

咱们分别在 PHP5.三、PHP 5.6 和 PHP 7 中运行这两段代码。

 

[root@localhostphpperf]# time phpobject.php

 

real 0m2.144s

user 0m2.119s

sys 0m0.009s

[root@localhostphpperf]# time phpobject.php

 

real 0m2.106s

user 0m2.089s

sys 0m0.013s

[root@localhostphpperf]# time php object1.php

 

real 0m1.421s

user 0m1.402s

sys 0m0.016s

[root@localhostphpperf]# time php object1.php

 

real 0m1.431s

user 0m1.410s

sys 0m0.012s

 

在 PHP 5.3 中,数组版比对象版快了近30%。

 

[root@localhostphpperf]# time php56 object.php

 

real 0m1.323s

user 0m1.319s

sys 0m0.002s

[root@localhostphpperf]# time php56 object.php

 

real 0m1.414s

user 0m1.400s

sys 0m0.006s

[root@localhostphpperf]# time php56 object1.php

 

real 0m1.356s

user 0m1.352s

sys 0m0.002s

[root@localhostphpperf]# time php56 object1.php

 

real 0m1.364s

user 0m1.349s

sys 0m0.006s

[root@localhostphpperf]# time php7 object.php

 

real 0m0.642s

user 0m0.638s

sys 0m0.003s

[root@localhostphpperf]# time php7 object.php

 

real 0m0.606s

user 0m0.602s

sys 0m0.003s

[root@localhostphpperf]# time php7 object1.php

 

real 0m0.615s

user 0m0.613s

sys 0m0.000s

[root@localhostphpperf]# time php7 object1.php

 

real 0m0.615s

user 0m0.611s

sys 0m0.003s

 

到了 PHP 5.6 和 PHP7 中,两个版本基本没有差异,而在 PHP7 中的速度是 PHP5.6 中的2倍。在新的版本中,差异已几乎没有,那么为了清楚起见咱们固然应该声明类,实例化类来存储对象数据。

 

2.八、getter 和 setter

 

从 Java 转过来学习 PHP 的朋友,在对象声明时,可能习惯使用 getter 和 setter,那么,在 PHP 中,使用 getter 和 setter 是否会带来性能上的损失呢?一样,先上例子。

 

无 setter版:

classUser
{
public $uid;
public $username;
public $age;
function getUserInfo()
    {
return "UID:".$this->uid." UserName:".$this->username." Age:".$this->age;
    }
}

for($i=0; $i<1000000;$i++) {
$user = new User();
$user->uid= $i;
$user->age = $i%100;
$user->username="User".$i;
$user->getUserInfo();
}

有 setter版:

 

classUser
{
public $uid;
private $username;
public $age;
function setUserName($name)
    {
$this->username = $name;
    }
function getUserInfo()
    {
return "UID:".$this->uid." UserName:".$this->username." Age:".$this->age;
    }
}

for($i=0; $i<1000000;$i++) {
$user = new User();
$user->uid= $i;
$user->age = $i%100;
$user->setUserName("User".$i);
$user->getUserInfo();
}

这里只增长了一个 setter。运行结果以下:

 

[root@localhostphpperf]# time php7 object.php

 

real 0m0.607s

user 0m0.602s

sys 0m0.004s

[root@localhostphpperf]# time php7 object.php

 

real 0m0.598s

user 0m0.596s

sys 0m0.000s

[root@localhostphpperf]# time php7 object2.php

 

real 0m0.673s

user 0m0.669s

sys 0m0.003s

[root@localhostphpperf]# time php7 object2.php

 

real 0m0.668s

user 0m0.664s

sys 0m0.004s

 

从上面能够看到,增长了一个 setter,带来了近10%的效率损失。可见这个性能损失是至关大的,在 PHP 中,咱们没有必要再来作 setter 和 getter了。须要引用的属性,直接使用便可。

 

2.九、类属性该声明仍是不声明

 

PHP 自己支持属性能够在使用时增长,也就是不声明属性,能够在运行时添加属性。那么问题来了,事先声明属性与过后增长属性,是否会有性能上的差异。这里也举一个例子探讨一下。

 

事先声明了属性的代码就是2.8节中,无 setter 的代码,再也不重复。而无属性声明的代码以下:

classUser
{ 
function getUserInfo()
    {
return "UID:".$this->uid." UserName:".$this->username." Age:".$this->age;
    }
}

for($i=0; $i<1000000;$i++) {
$user = new User();
$user->uid= $i;
$user->age = $i%100;
$user->username="User".$i;
$user->getUserInfo();
}

两段代码,运行结果以下:

 

[root@localhostphpperf]# time php7 object.php

 

real 0m0.608s

user 0m0.604s

sys 0m0.003s

[root@localhostphpperf]# time php7 object.php

 

real 0m0.615s

user 0m0.605s

sys 0m0.003s

[root@localhostphpperf]# time php7 object3.php

 

real 0m0.733s

user 0m0.728s

sys 0m0.004s

[root@localhostphpperf]# time php7 object3.php

 

real 0m0.727s

user 0m0.720s

sys 0m0.004s

 

从上面的运行能够看到,无属性声明的代码慢了20%。能够推断出来的就是对于对象的属性,若是事先知道的话,咱们仍是事先声明的好,这一方面是效率问题,另外一方面,也有助于提升代码的可读性呢。

 

2.十、图片操做 API 的效率差异

 

在图片处理操做中,一个很是常见的操做是将图片缩放成小图。缩放成小图的办法有多种,有使用 API 的,有使用命令行的。在 PHP 中,有 imagick 和 gmagick 两个扩展可供操做,而命令行则通常使用 convert 命令来处理。咱们这里来讨论使用 imagick 扩展中的 API 处理图片的效率差异。

 

先上代码:

 

function imagick_resize($filename, $outname)
{
$thumbnail = new Imagick($filename);
$thumbnail->resizeImage(200, 200, imagick::FILTER_LANCZOS, 1);
$thumbnail->writeImage($outname);
unset($thumbnail);
}

function imagick_scale($filename, $outname)
{
$thumbnail = new Imagick($filename);
$thumbnail->scaleImage(200, 200);
$thumbnail->writeImage($outname);
unset($thumbnail);
}


function convert($func)
{
$cmd= "find /var/data/ppt |grep jpg";
$start = microtime(true);
exec($cmd, $files);
$index = 0;
foreach($files as $key =>$filename)
    {
$outname= " /tmp/$func"."_"."$key.jpg";
$func($filename, $outname);
$index++;
    }
$end = microtime(true);
echo "$func $index files: " . ($end- $start) . "s\n";
}

convert("imagick_resize");
convert("imagick_scale");

在上面的代码中,咱们分别使用了 resizeImage 和 scaleImage 来进行图片的压缩,压缩的是常见的 1-3M 之间的数码相机图片,获得以下运行结果:

 

[root@localhostphpperf]# php55 imagick.php

 

imagick_ resize 169 files: 5.0612308979034s

imagick_ scale 169 files: 3.1105840206146s

 

[root@localhostphpperf]# php55 imagick.php

 

imagick_ resize 169 files: 4.4953861236572s

imagick_ scale 169 files: 3.1514940261841s

 

[root@localhostphpperf]# php55 imagick.php

 

imagick_ resize 169 files: 4.5400381088257s

imagick_ scale 169 files: 3.2625908851624s

 

169张图片压缩,使用 resizeImage 压缩,速度在4.5S以上,而使用 scaleImage 则在 3.2S 左右,快了将近50%,压缩的效果,用肉眼看不出明显区别。固然 resizeImage 的控制能力更强,不过对于批量处理而言,使用 scaleImage 是更好的选择,尤为对头像压缩这种频繁大量的操做。本节只是例举了图片压缩 API 做为例子,也正像 explode 和 preg_ split 同样,在 PHP 中,完成一样一件事情,每每有多种手法。建议采用效率高的作法。

 

以上就是关于 PHP 开发的10个方面的对比,这些点涉及到 PHP 语法、写法以及 API 的使用。有些策略随着 PHP 的发展,有的已经再也不适用,有些策略则会一直有用。

 

有童鞋也许会说,在现实的开发应用中,上面的某些观点和解决策略,有点「然并卵」。为何这么说呢?由于在一个程序的性能瓶颈中,最为核心的瓶颈,每每并不在 PHP 语言自己。即便是跟 PHP 代码中暴露出来的性能瓶颈,也常在外部资源和程序的不良写法致使的瓶颈上。因而为了作好性能分析,咱们须要向 PHP 的上下游戏延伸,好比延伸到后端的服务上去,好比延伸到前端的优化规则。在这两块,都有了至关多的积累和分析,雅虎也据此提出了多达35条前端优化规则,这些同 PHP 自己的性能分析构成了一个总体,就是下降用户的访问延时。

 

因此前面两部分所述的性能分析,只是有助于你们了解 PHP 开发自己,写出更好的 PHP 程序,为你成为一个资深的 PHP 程序员打下基础,对于实际生产中程序的效率提高,每每帮助也不是特别显著,由于你们也看到,在文章的实例中,不少操做每每是百万次才能看出明显的性能差异。在现实的页面中,每个请求很快执行完成,对这些基础代码的调用,每每不会有这么屡次调用。不过了解这些,老是好的。

相关文章
相关标签/搜索