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