2

五、PHP性能改进在生产中的实践
5.1、XHProf
首先来看一下XHProf这个工具,怎么能改进我们的PHP语言本身。

首先安装这个工具,就是模块化安装。
我们封装一下操作类。

<?php
/** 
 * 优才网公开课示例代码 
 * 
 * XHProf 封装类
 * 
 * @author 伍星 
 * @see http://www.ucai.cn 
 */  

class XHProf
{

    public function __construct()
    {
        // start profiling
        $XHPROF_ROOT = "/home/wwwroot/ucai_app/samples";
        include_once $XHPROF_ROOT . "/xhprof_lib/utils/xhprof_lib.php";
        include_once $XHPROF_ROOT . "/xhprof_lib/utils/xhprof_runs.php";
    }

    public function beginProf()
    {
        xhprof_enable();

        register_shutdown_function('XHProf::endProf');
    }

    public function endProf()
    {
        $xhprof_data = xhprof_disable();

        $xhprof_runs = new XHProfRuns_Default();
        $run_id = $xhprof_runs->save_run($xhprof_data, "xhprof_foo");

        echo "<a href=\"http://samples.app.ucai.cn/xhprof_html/index.php?run=$run_id&source=xhprof_foo\">性能分析结果</a>";
    }

}

值得注意的是这句话:

register_shutdown_function('XHProf::endProf');

什么意思呢,就是在整个页面完成了之后,输出结果报表链接。

5.2 、Opcache的安装与配置
其次我们来看看 opcache,安装过程没有什么讲的,主要是推荐一个配置,并且需要强调,opcache不是PHP extension,是zend extension, 所以非常容易出错。配置如下:

[opcache]
zend_extension="/usr/local/php/lib/php/extensions/no-debug-zts-20090626/opcache.so"
opcache.enable_cli=1
opcache.memory_consumption=128      //共享内存大小, 这个根据你们的需求可调
opcache.interned_strings_buffer=8   //interned string的内存大小, 也可调
opcache.max_accelerated_files=4000  //最大缓存的文件数目
opcache.revalidate_freq=60          //60s检查一次文件更新
opcache.fast_shutdown=1             //打开快速关闭, 打开这个在PHP Request Shutdown的时候
                                    //   会收内存的速度会提高
opcache.save_comments=0             //不保存文件/函数的注释

5.3、Yaf和Phalcon
再次来看两个C语言写的PHP框架

第一个介绍的是Yaf 框架,这是一个纯C语言框架。具体的安装过程和实验如下:
1、从github 下载 php-yaf https://github.com/laruence/php-yaf

2、解压,按PHP模块的编译手法编译

phpize
./configure --with-php- /usr/local/php/bin/php-config 
make
make install

3、在php.ini 中配置

extension = "yaf.so"
yaf.environ="product"

4、通过命令行上执行 php –m|grep yaf 你就能看到模块已经安装好了。

5、余下的就是Web测试。
在源码目录下,找到

php-yaf-master/tools/cg
./yaf_cg ucai_gkk

6、将output 目录下的 ucai_gkk 移至 samples.app.ucai.cn 所在的目录下,就可以通过 http://samples.app.ucai.cn/ucai_gkk
来访问。

7、我们可以做一下改造实验,了解一下这个框架的基本结构。
请输入图片描述
大家可以看到,我只是一通过一个工具,就生成了整个程序的框架,就可以根据需要,添加自己的业务逻辑。
比如 ,在models/Sample.php 中增加一个方法,

public function selectProductSample()
    {
        return "<h1>Hello Haha</h1>";
    }

在 views 目录下新建文件,product/index.phtml

<?php
/** 
 * 优才网公开课示例代码 
 * 
 * Yaf 视图
 * 
 * @author 伍星 
 * @see http://www.ucai.cn 
 */  
echo $content, " I am ", $name, " From Product";
?>

在controllers 目录下建立 Product.php

<?php
/** 
 * 优才网公开课示例代码 
 * 
 * Yaf 控制器
 * 
 * @author 伍星 
 * @see http://www.ucai.cn 
 */  

/**
 * @name IndexController
 * @author root
 * @desc 默认控制器
 * @see http://www.php.net/manual/en/class.yaf-controller-abstract.php
 */
class ProductController extends Yaf_Controller_Abstract
{

    /**
     * 默认动作
     * Yaf支持直接把Yaf_Request_Abstract::getParam()得到的同名参数作为Action的形参
     * 对于如下的例子, 当访问http://yourhost/hello/index/index/index/name/root 的时候, 你就会发现不同
     */
    public function indexAction($name = "Product")
    {
        //1. fetch query
        $get = $this->getRequest()->getQuery("get", "default value");

        //2. fetch model
        $model = new SampleModel();

        //3. assign
        $this->getView()->assign("content", $model->selectProductSample());
        $this->getView()->assign("name", $name);

        //4. render by Yaf, 如果这里返回FALSE, Yaf将不会调用自动视图引擎Render模板
        return TRUE;
    }

}

这样我们就可以通过,http://samples.app.ucai.cn/hello/?a=index&c=product,这样的链接来访问,我们新建的内容了。操作起来很简单。

用同样的方式,我们安装Phalcon。虽然从形式上,它更简单。通过目录就知道,内容更为丰富。

这也是Yaf跟Phalcon的很大的不同之处,Yaf尽管效率很高,但是要在生产上使用,还是略显单薄,功能不够丰富。而Phalcon则真的是功能很全的。正像优才网培养的叫全栈工程师,而Phalcon也号称自己是Full Stack 的一个框架。

这次,没有工具来生成一个基本的框架,但是我们可以从Github上的一个教程,作为切入点。
https://github.com/phalcon/tutorial
下载了这个教程之后,我们就可以开始动手了。先看看功能 。
放到相应的目录下之后,比如 http://samples.app.ucai.cn 目录下之后,得配置一下rewrite 规则。

 rewrite ^/phalcon/(.*?)$ /phalcon/public/index.php?_url=/$1 last;
    rewrite ^/phalcon$ /phalcon/public/index.php last;

然后,通过 http://samples.app.ucai.cn/phalcon/ 可以访问。

发现有一个注册功能,那我们就来想这个数据怎么保存的。
发现在 public/index.php 中有一段配置,

 //Set the database service
 $di->set('db', function() {
        return new \Phalcon\Db\Adapter\Pdo\Mysql(array(
            "host" => "127.0.0.1",
            "username" => "xxxx",
            "password" => "xxxxx",
            "dbname" => "xxxxxx"
        ));
    });

我们在这里改了配置了之后,再看看提交的情况。
发现在SignupControll.php 中有一段保存代码 ,

$user = new Users();
        $user->name = $name;
        $user->email = $email;


        //Store and check for errors
        if (($userid = $user->save()) == true)
        {
            echo 'Thanks for register!';
        } else
        {
            echo 'Sorry, the next problems were generated: ';
            foreach ($user->getMessages() as $message)
            {
                echo $message->getMessage(), '<br/>';
            }
        }

过去看这个 models/Users.php 却是空的?
我们在不修改Users.php的时候,看看是否能将数据保存进去?

当然前提是建一个表,因为我怀疑,这存在某种关系 的映射。

CREATE TABLE `users` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(70) NOT NULL,
  `email` varchar(70) NOT NULL,
  PRIMARY KEY (`id`)
);

发现果不其然,保存进去了,好,我们再进一步,找一现实中可能会用的表格格式,比如下划线的表格 users_exinfo。

CREATE TABLE `users_exinfo` (
  `id` int(10) unsigned NOT NULL default 0,
  `schoolname` varchar(70) NOT NULL,
  `age` int NOT NULL,
  PRIMARY KEY (`id`)
);

看看能否实现保存,于是乎也建了一个空类。

class UsersExinfo extends Phalcon\Mvc\Model{

}

同时也修改了视图,将数据保存了进去。
请输入图片描述

结果如下:
请输入图片描述

大家看到,成功地保存了数据。

5.4、zephir高效开发模块
好的,讲到这里,衍生出一个小话题,就是开发模块。
在PHP里,开发模块,是一个很痛苦的过程。因为C语言,大家都知道,是出了名的难学的,值得高兴的是,也是Phalcon这个团队的童鞋们,也为我们准备了一个高效的开发模块的语言,称之为zephir。正因为扩展如此难以开发,但是扩展又是如此高效,所以我们要用高效的方式来开发扩展。

git clone https://github.com/phalcon/zephir.git
cd zephir/
mv zephir /usr/local/

然后就可以开发模块了,我们使用
zephir init gkk
生成模块的框架,
然后 cd gkk/gkk
编写 hello.zep
namespace Gkk;

/**
 * This is a sample class
 */
class Welcome
{
    /**
     * This is a sample method
     */
    public function welcome()
    {
        echo "你们好!参加优才网公开课的同学们!";
    }

    public function say()
    {
        echo "今天是优才网第三十三讲公开课了!";
    }


}

然后再返回

zephir compile
zephir build

然后在 php.ini 中配置

extension=gkk.so

通过 php –m 可以看到相应的模块。再编写
test.php

<?php

$t = new Gkk\Welcome();
$t->say();
echo "\n";
?>

就能看到相应的输出。

5.5、各框架性能总结
好的,有关两个用C开发的框架和相关内容我们就介绍到这里。下面我们来总结一下框架,以及做一些性能评测。
首先来看一下性能评测报告,这是一个专门测框架的github项目出的数据,
请输入图片描述

博客在这里,
https://github.com/eryx/php-framework-benchmark

从上面的图可以看到,两个用C编写的框架,性能还是相当可观的。Yaf比Phalcon性能更强,也不奇怪。因为结构更为简单,模块更少。同时也发现,像zend framework这样的框架,是不能轻易在一个大众的互联网产品中使用的,尽管代码写得不错,但是效率太低了,有木有!

5.6、PHP的重写
在评测之前,大家记起来了没有,我们上面讲了六点,其中有一点是什么?重写PHP!
那就看看,哪些业界人士,在PHP重写的路子上做了非常激动人心的尝试。
刚才讲了,谁最有动力?有两个方面的人有动力,一个是PHP最大的使用者,一个是PHP官方。最大的使用者,他对PHP的提升,能大幅度地减少资源的占用,一个百分之几的优化可能就是成百上千台设备的节省。而后者,则要想到如果PHP本身效率提升不上去,在未来的发展过程中,很容易出现转折,尽管现在还是非常火的。

所有从官方,就有了,PHPng,这个我没有安装过,有兴趣的同学,可以自己去折腾,https://wiki.php.net/phpng 值得一提的是,咱们国内的鸟哥是这个项目的主要参与者之一。Yaf也是他的作品。而另外一个,则是Facebook主导的,HHVM,其前身是HipHop, 当时的思路是把PHP全部编译成C++程序,在上线的过程中,上线的是一个二进制包,非常不灵活,修改代码,需要发包才能生效。如果出现故障,会有灾难性的影响。所以演进到现在成了HHVM,全称是HipHop Virtual Machine。
现在的模式,简单了讲就是可以做为FastCGI 的运行容器。大家安装过LNMP的同学就知道,在Nginx的后端,也就是说Nginx的配置中,通过fastcgi_pass  这个配置指向了实际运行PHP的FastCGI 运行容器,PHP自带的是PHP-FPM(FastCGI Process Manager),而HHVM就是可以一定程度上无缝地替换掉,FPM,比如你kill掉FPM进程,通过

hhvm --mode server -vServer.Type=fastcgi -vServer.Port=9000 &来启动HHVM。都不需要修改nginx 配置。就可以访问了。但是性能一定程度上,大有提升。
这枚神器有如下特点:
•当然不是小团队能玩的
•与PHP 5.2引擎+APC相比,可以处理的Web请求吞吐量增加了9倍,而内存消耗减少了5倍。
•如无特殊模块,可以无缝替换 php-fpm(除了极少数兼容问题)

•1、优点
–FB出品
–强大到令你吃惊,数十倍的性能提升
–已经趋于稳定,无缝替换 PHP-FPM

•2、缺点
–还不是很稳定
–模块需要迁移


张友林
974 声望153 粉丝

写代码多年的程序猿,目前致力于在线教育行业,边写代码边讲课