ホームページ >php教程 >php手册 >关于PHP的编译和执行分离

关于PHP的编译和执行分离

WBOY
WBOYオリジナル
2016-06-06 20:07:361127ブラウズ

作者: Laruence( ) 本文地址: http://www.laruence.com/2012/08/16/2701.html 转载请注明出处 关于让PHP的编译和执行分离这个问题, 一直有人提, 也一直有人尝试. 提的人认为编译执行分离以后, 可以得到性能提升, 可以做代码保护等. 我本身并不是对这个特性很

  • 作者: Laruence(关于PHP的编译和执行分离 关于PHP的编译和执行分离 关于PHP的编译和执行分离 关于PHP的编译和执行分离)
  • 本文地址: http://www.laruence.com/2012/08/16/2701.html
  • 转载请注明出处

关于让”PHP的编译和执行分离”这个问题, 一直有人提, 也一直有人尝试. 提的人认为编译执行分离以后, 可以得到性能提升, 可以做代码保护等.

我本身并不是对这个特性很感冒, 因为这里面存在一个投入产出比. 让我来给大家解释一下, 然而不管怎么样, 在最后我会给大家提供一种方案来实现这个功能.

1. PHP的编译并不是很耗时

我之前的文章也介绍过, PHP的编译是线性的编译过程, 不做优化, 所以这个过程非常之快. 而编译和执行分离这个特性的提出着认为分离以后, 可以省掉编译过程, 会有很大的性能提升.

后记, 有同学提出, 编译和执行分离以后, 就可以在编译的时候做各种优化, 从而影响执行速度. 这个确实是个值得研究的方向.

2. 开发速度

PHP的一个优点就是开发/部署/调试非常方便, 快速, 更改立即见效, 这个当大家在十万火急的情况下修复线上bug的时候会感受更加深刻, :) 而如果我们采用了编译/执行分离以后, 那么更改就需要首先编译, 然后部署, 然后才能生效, 这对于开发来说, 并不是什么好事.

3. 我们有APC/Zend O+等第三方的代码缓存工具

APC等第三方的代码缓存工具(Opcodes Cache)已经相对比较成熟, 并对开发者透明, 大家只要在服务器上安装了APC, 就可以得到编译/执行分离的性能提升.

4. 简单的编译/执行分离, 并不能很好的实现代码保护

原因很简单, PHP的编译不做优化, 所以很容易被反编译. 当然, 我也不否认, 采用二进制内容确实有一些作用.

另外, 还有一些因素, 比如编译/执行分离这个方案是有人在做的, 但是还不成熟等等.

最后呢, 其实我们目前也是可以做到的, 在这里我给大家提供一个类似的解决方案.

首先, 我要打个广告, 以后APC将由我来维护, 大家以后在APC的使用中如果有问题, 可以直接联系我. :)

回归正题: 要实现编译和执行分离, 其实我们借助APC就能做到, APC提供了一族apc_bin_dump, apc_bin_load函数, 能把Opcodes缓存导出到外部文件中.

然而, 可惜的是, 这部分功能以前一直不能很好的正常工作, 这和之前的开发者因为时间原因不在投精力在这个上面是有关系的.

经过我对apc_bin系列函数的重新梳理, 修复以后, 这部分功能现在终于可以正常工作了(从APC-3.1.12开始), 那么基于这些函数, 我们就可以实现编译执行分离.

思路很简单, 在本地通过apc_bin_dumpfile把我们的php文件, 导出成bin文件, 然后在服务器上通过apc_bin_loadfile来读取这些bin文件. 就可以实现编译和执行分离啦, 一个简单的示意代码如下:

$ find ./ -name "*.php" -exec php -r "apc_bin_dumpfile(array('{}'), array(), '{}' . '.bin');" \;

然后在服务器端的文件自动加载部分:

<?php function __autoload($name) {
       /*首先计算出文件名字*/
       $file =  根据类名得到PHP文件路径();
       if (!file_exists($file)) {
          //文件不存在, 说明我们还没有load过, 那么创建一个空文件.
          file_put_contents($file, '');
          apc_bin_loadfile($file . '.bin');
       } else {
          //我们已经load过了, 理论上应该已经被服务器的APC缓存处理Cache住了.
        }

       include ($file);
   }

当然, 这里只是一个简单的示意, 如果要实际使用, 你还要考虑缓存被换出的可能, 那么一个解决方案就是设置俩个自动加载函数, 第一个如上, 第二个如果被调用, 就说明缓存被换出, 导致include了一个空文件, 于是就再次load一次bin文件就可以了.

当然, 你也可以把所有的文件打包到一个bin文件中, 然后只load一次, 后续就交给服务器上的APC Cache来做就可以了. 但是这里有一个要注意的点就是,

那么对于这部分希望”代码保护”功能的人来说, 就可以使用APC来免费的完成这些事情了. 当然, 因为是内存镜像dump, 所以要受PHP版本和系统的大小端影响, 不过对于一般的应用来说, 这个倒可以很容易做到匹配.

最后, thanks to @cfc4n同学, 在这件事情上的推动, 呵呵


Comments

  • 2012/08/16, 非洲黑馒头 writes: 抢占沙发
  • 2012/08/16, 烽火 writes: 老黑你幼稚不
  • 2012/08/16, Demon writes: 如果我说在一起,鸟哥会不会生气。在一起!在一起!在一起!
  • 2012/08/16, beimuaihui writes: 太好了,又可加速又可保护代码.
  • 2012/08/16, 大草原 writes: 在一起!在一起!在一起!在一起!在一起!在一起!在一起!在一起!在一起!
  • 2012/08/16, loki writes: 拿到这些bin文件,再apc_bin_loadfile,那也起不到代码保护的左右- -
  • 2012/08/16, 大力水手 writes: APC终于有希望了,哈哈哈
  • 2012/08/16, hileon writes: PHP的一个优点就是开发/部署/调试非常`方案` 是 `方便`吧
  • 2012/08/16, wclssdn writes: 就算不用这种方法, 直接开启apc. 不也会缓存住opcode么? 一直也不是很了解apc. 一直认为的就是开启了它, 只要php文件没发生修改. 那只要执行过一次,再下一次执行的时候, apc就会略过它的编译过程. 直接执行上次编译过的结果.. 是这样么?
  • 2012/08/16, PHP小菜鸟 writes: 慢慢研究
  • 2012/08/17, hellokitty writes: 貌似没有for windows的版本下载,最新的是3.1.10
  • 2012/08/17, sesehai writes: APC 目前是否支持 PHP-5.4.4呢?
  • 2012/08/17, 雪候鸟 writes: @sesehai 支持
  • 2012/08/20, crazymartian writes: 支持window是吗?
  • 2012/08/20, MC writes: 见教了,非常好
  • 2012/08/24, 关于PHP的编译和执行分离树林/咖啡 成都专业php网站制作 | 树林/咖啡 成都专业php网站制作 writes: [...] 风雪之隅 ? PHP应用 Posted in: php / Tagged: 关于PHP的编译和执行分离 [...]
  • 2012/08/24, sevensoile writes: 前辈你好。我有个问题想问下,现在我在网站后台架构上产生了好大的疑问。两个选择:1。php的现有框架(yii,zf,yaf)2。后台使用java和c语言来做逻辑处理和数据库操作,中转用thrift给php 重点是并行处理上和速度上,我不知道怎么平衡这个问题。 希望前辈指点下,新浪微薄后台也是用php的么?
  • 2012/08/25, 关于PHP的编译和执行分离 | 奇言妙事-文学奇谈小小说阅读xlinblog.sinaapp.com writes: [...] 本文地址: http://www.laruence.com/2012/08/16/2701.html [...]
  • 2012/08/29, wee writes: 看完前一篇和这一篇之后,忽然想到一个略有些离题的事情: php对windows环境的支持。 自从windows.php.net出现之后,php本身对于windows的支持已经大致上没什么严重的问题,现在的矛盾卡在扩展上。 php的扩展,除了windows版本的发行包中间已经附带的那些之外,其他的想找到供windows环境用的.dll文件那是相当的困难,PECL For Windows已经说了N年了,始终不见动静,到目前为止基本上只能指望http://downloads.php.net/pierre/这个页面上的那些文件。问题是这里面基本就没有PHP5.4可用的扩展……于是我只好一边对着5.4的几个新特性流口水一边咬牙继续用5.3。为啥?项目里对几个扩展依赖很大,比如http,imagick,oauth……5.4的新特性诱惑很大,但是还不足以抵消解决这几个扩展带来的成本。 肯定有人说为啥服务器要用windows环境?理由类似于上一篇的“关于语言的选用”,理由就是“易用”。尤其是考虑到安全因素之后。windows server 2k8r2的环境可以很放心的交给开发人员花一点点时间打理即可,linux环境,就必须认真考虑养一个专职的维护人员。 所以我是不太明白为什么pecl在对windows的支持这上面特别不给力,也许某些扩展在实现上导致了很难提供对windows的支持,但是已经在5.2和5.3上有提供的那些,要提供对应5.4的版本应该不难吧? 也曾经在之前的某个文章里看到鸟哥提到编译windows版本的扩展并不难,但是我就一直找不到一个像样的教程,鸟哥能写一个不?对于并不精通C的PHP用户来说,怎样做才能编译出windows版本的pecl扩展来?
  • 2012/08/29, smallyang writes: 水一个:想起一句话,聊天止与呵呵
  • 2012/08/31, Anonymous writes: apc相比eaccelerator性能如何, 我之前做过测试, 使用apc的程序qps要比ea慢了1倍所有.
  • 2012/09/14, 奇言妙事-文学奇谈小小说阅读xlinblog.sinaapp.com » 再一次, 不要使用(include/require)_once writes: [...] 关于PHP的编译和执行分离 [...]
  • 2012/10/29, jianwu writes: 不错! 以后就基本直接执行底层C代码了~ 不过以后应该增加相应管理工具了。比如每次修改php自动编译成apc.bin等
  • 2012/11/10, 张 健 writes: 崇拜前辈啊
  • 2012/11/29, 使用APC来保护PHP代码 | CNXCT小组的博客 writes: [...] 早在3-4个月之前,鸟哥博客上一篇文章《关于PHP的编译和执行分离》中提到APC来作为PHP代码保护的方案。从文中可以看出,鸟哥的想法是每个php文件,导出一个opcode 的bin文件,加载时,也是挨个加载,这样也实现了代码保护,但一个项目几百个php文件的话,也得相应存在几百个bin文件,量比较大,操作比较复杂,管理不方便,不好做版本验证(以后会提到)。末学比较倾向于单个bin文件的导出,单个opcode bin文件的加载。而且,单个bin文件的加载,可以避免项目中出现部分文件跟整体版本不一致的情况发生,运维同事再也不用担心个别文件跟整个项目版本不一致的情况了。 [...]
  • 2012/11/29, 使用APC来保护PHP代码 | 安全-脚本-运维 K. writes: [...] 早在3-4个月之前,鸟哥博客上一篇文章《关于PHP的编译和执行分离》中提到APC来作为PHP代码保护的方案。从文中可以看出,鸟哥的想法是每个php文件,导出一个opcode 的bin文件,加载时,也是挨个加载,这样也实现了代码保护,但一个项目几百个php文件的话,也得相应存在几百个bin文件,量比较大,操作比较复杂,管理不方便,不好做版本验证(以后会提到)。末学比较倾向于单个bin文件的导出,单个opcode bin文件的加载。而且,单个bin文件的加载,可以避免项目中出现部分文件跟整体版本不一致的情况发生,运维同事再也不用担心个别文件跟整个项目版本不一致的情况了。 [...]
  • 2012/12/06, dawsonJ writes: 请问php以后会实现类似c语言#ifdef之类的预编译指令吗?
  • 2012/12/06, 关于PHP的编译和执行分离 | 5iphp writes: [...] 本文地址: http://www.laruence.com/2012/08/16/2701.html [...]
  • 2013/01/19, gaodi07 writes: 相信APC越来越好
  • 2013/01/27, dailingang writes: 我用的时候遇到一个问题 b(); ?> 加载成功 但是报告 Class 'a' not found 这是为什么啊
  • 2013/01/27, Anonymous writes: 我用的时候遇到一个问题 //t.php class a{ public b(){ return 'a'; } } //dump.php apc_bin_dumpfile(array(dirname(__FILE__).'\t.php'),array(),'t2.bin'); //test.php $res = apc_bin_load(file_get_contents('t2.bin')); var_dump($res);//exit; $c = new a(); echo $c->b(); 加载成功 但是报告 Class 'a' not found 这是为什么啊
  • 2013/03/05, php writes: 真的受教了,原来PHP也这么强大
  • 2013/04/28, Yac (Yet Another Cache) – 无锁共享内存Cache | 午后小憩 writes: [...] 关于PHP的编译和执行分离 [...]
  • 2013/04/30, 再一次, 不要使用(include/require)_once | 午后小憩 writes: [...] 关于PHP的编译和执行分离 [...]
  • 2013/04/30, PHP & “Data” URL scheme | 午后小憩 writes: [...] 关于PHP的编译和执行分离 [...]
  • 2013/05/01, 关于PHP的编译和执行分离 | 午后小憩 writes: [...] 本文地址: http://www.laruence.com/2012/08/16/2701.html [...]
  • 2013/05/02, Taint-0.3.0(A XSS codes sniffer) released | 午后小憩 writes: [...] 关于PHP的编译和执行分离 [...]
  • 2013/05/15, Accepting the things that happen to you in your life with grace and wisdom is a worthy goal. While we get into challenging situations often which test both grace and wisdom, the goal is to act and react gracefully as much as possible. It strengthens our c writes: Foarte bine, e un pas inainte.
  • 2013/07/31, lein writes: 请教关于apc的使用 bin_dump的文件怎么使用呢,网上找到的代码都不够详细,手册上也没有示例。 我的代码: 1 被dump的文件(/www/f1.php): '.chr(10); function dosome(){ echo date('Y-m-d H:i:s'); } 2 执行dump的文件(/www/f2.php):
  • 2013/07/31, lein writes: @鸟哥 啊 为什么要这句? include($file); 并且$file是个空文件,怎么确定apc会从缓存中找这个$file而不是去找这个空文件呢?
  • 2014/01/02, www.tonitech.com的站长 writes: 我最近也在考虑这个问题,如果把php这个解释型语言变成编译型语言是不是运行效率会很高?考虑到开发的效率可以再开发的时候继续扮演解释型语言,到正式环境的时候摇身一变成为编译型语言,这样如何?
  • 2014/05/05, php_4年生 writes: hip-hop不是可以吗

Related posts:

  • PHP RFC: 让PHP的foreach支持list

Copyright © 2010 风雪之隅 版权所有, 转载务必注明. 该Feed只供个人使用, 禁止未注明的转载或商业应用. 非法应用的, 一切法律后果自负. 如有问题, 可发E-mail至my at laruence.com.(Digital Fingerprint: 73540ba0a1738d7d07d4b6038d5615e2)
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。