PHP Opcode缓存加速组件:APC模块安装使用
发布:smiling 来源: PHP粉丝网 添加日期:2018-09-17 09:29:00 浏览: 评论:0
什么是opcode
也许你曾经尝试过用C/C++编写动态内容,虽然开发过程极其繁琐,但为了获得性能提升,这样做或许是值得的,它们可以将动态内容编译成二进制可执行文件,也就是目标代码,由操作系统进程直接装载运行。如今已经很少有人使用C/C++编写动态内容了,绝大多数的Web开发人员享受着当下的幸福时光,很多优秀的脚本语言可供选择,比如PHP,Ruby,Python,它们都属于解释型语言,所以用它们编写的动态内容都需要依赖响应的解释器程序来运行。
解释器程序也是一个二进制可执行文件,比如/bin/ruby,它同样可以直接在进程中运行,在运行过程中,解释器程序需要对输入的脚本代码进行分析,领会它们的旨意,然后执行它们。比如下面我们调用PHP的解释器,让它执行一段简单的脚本代码:
~ zfs$ php -r 'print 1+1;'
很好,它很快的输出了正确的结果,也许你觉的1+1的计算太小儿科,的确,在人类的大脑中计算1+1是很简单,几乎不用思考,但解释器的工作方式可不是你想象的那样,1+1和100+1000对它来说几乎没有什么区别,因为解释器核心引擎根本看不懂这些脚本代码,无法直接执行,所以需要进行一系列的代码分析工作,当解释器完成对脚本代码的分析后,便将它们生成可以直接运行的中间代码,也称为操作码(Operate Code,opcode)。
从程序代码到中间代码的这个过程,我们称为解释(parse),它由解释器来完成。如此相似的是,编译型语言中的编译器(如C语言的编译器gcc),也要将程序代码生成中间代码,这个过程我们称为编译(compile)。编译器和解释器的一个本质不同在于,解释器在生成中间代码后,便直接执行它,所以运行时的控制权在解释器;而编译器则将中间代码进一步优化,生成可以直接运行的目标程序,但不执行它,用户可以在随后的任意时间执行它,这时的控制权在目标程序,和编译器没有任何关系。
事实上,就解释和编译本身而言,它们的原理是相似的,都包括词法分析,语法分析,语义分析等,所以,有些时候将解释型语言中生成opcode的过程也称为"编译",需要你根据上下文来理解。
那么,opcode究竟是什么样的呢? 它又是如何解释生成的呢? 我们以PHP为例,来寻找这些答案。
PHP解释器的核心引擎为Zend Engine,可以很容易的查看它的版本:
- ~ zfs$ php -v
- PHP 5.5.14 (cli) (built: Sep 9 2014 19:09:25)
- Copyright (c) 1997-2014 The PHP Group
- Zend Engine v2.5.0, Copyright (c) 1998-2014 Zend Technologies
还记得前面我们曾经用PHP计算1+1的脚本代码吗? 我们来看看这段代码的opcode。在此之前,需要安装PHP的Parsekit扩展,它是一个用C编写的二进制扩展,由PECL来维护。有了Parsekit扩展后,我们就可以通过它提供的运行时API来查看任何PHP文件或者代码段的opcode。我们直接在命令行中调用parsekit_compile_string(),如下所示:
/usr/local/php/bin/php -r "var_dump(parsekit_compile_string('print 1+1;'));"
这样一来,我们便获得了这段代码的opcode,返回的是数组形式,结果如下所示:
- array(20) {
- ["type"]=>
- int(4)
- ["type_name"]=>
- string(14) "ZEND_EVAL_CODE"
- ["fn_flags"]=>
- int(0)
- ["num_args"]=>
- int(0)
- ["required_num_args"]=>
- int(0)
- ["pass_rest_by_reference"]=>
- bool(false)
- ["uses_this"]=>
- bool(false)
- ["line_start"]=>
- int(0)
- ["line_end"]=>
- int(0)
- ["return_reference"]=>
- bool(false)
- ["refcount"]=>
- int(1)
- ["last"]=>
- int(5)
- ["size"]=>
- int(5)
- ["T"]=>
- int(2)
- ["last_brk_cont"]=>
- int(0)
- ["current_brk_cont"]=>
- int(4294967295)
- ["backpatch_count"]=>
- int(0)
- ["done_pass_two"]=>
- bool(true)
- ["filename"]=>
- string(17) "Parsekit Compiler"
- ["opcodes"]=>
- array(5) {
- [0]=>
- array(8) {
- ["address"]=>
- int(33847532)
- ["opcode"]=>
- int(1)
- ["opcode_name"]=>
- string(8) "ZEND_ADD"
- ["flags"]=>
- int(197378)
- ["result"]=>
- array(3) {
- ["type"]=>
- int(2)
- ["type_name"]=>
- string(10) "IS_TMP_VAR"
- ["var"]=>
- int(0)
- }
- ["op1"]=>
- array(3) {
- ["type"]=>
- int(1)
- ["type_name"]=>
- string(8) "IS_CONST"
- ["constant"]=>
- &int(1)
- }
- ["op2"]=>
- array(3) {
- ["type"]=>
- int(1)
- ["type_name"]=>
- string(8) "IS_CONST"
- ["constant"]=>
- &int(1)
- }
- ["lineno"]=>
- int(1)
- }
- [1]=>
- array(7) {
- ["address"]=>
- int(33847652)
- ["opcode"]=>
- int(41)
- ["opcode_name"]=>
- string(10) "ZEND_PRINT"
- ["flags"]=>
- int(770)
- ["result"]=>
- array(3) {
- ["type"]=>
- int(2)
- ["type_name"]=>
- string(10) "IS_TMP_VAR"
- ["var"]=>
- int(1)
- }
- ["op1"]=>
- array(3) {
- ["type"]=>
- int(2)
- ["type_name"]=>
- string(10) "IS_TMP_VAR"
- ["var"]=>
- int(0)
- }
- ["lineno"]=>
- int(1)
- }
- [2]=>
- array(7) {
- ["address"]=>
- int(33847772)
- ["opcode"]=>
- int(70)
- ["opcode_name"]=>
- string(9) "ZEND_FREE"
- ["flags"]=>
- int(271104)
- ["op1"]=>
- array(4) {
- ["type"]=>
- int(2)
- ["type_name"]=>
- string(10) "IS_TMP_VAR"
- ["var"]=>
- int(1)
- ["EA.type"]=>
- int(0)
- }
- ["op2"]=>
- array(3) {
- ["type"]=>
- int(8)
- ["type_name"]=>
- string(9) "IS_UNUSED"
- ["opline_num"]=>
- string(1) "0"
- }
- ["lineno"]=>
- int(1)
- }
- [3]=>
- array(7) {
- ["address"]=>
- int(33847892)
- ["opcode"]=>
- int(62)
- ["opcode_name"]=>
- string(11) "ZEND_RETURN"
- ["flags"]=>
- int(16777984)
- ["op1"]=>
- array(3) {
- ["type"]=>
- int(1)
- ["type_name"]=>
- string(8) "IS_CONST"
- ["constant"]=>
- &NULL
- }
- ["extended_value"]=>
- int(0)
- ["lineno"]=>
- int(1)
- }
- [4]=>
- array(5) {
- ["address"]=>
- int(33848012)
- ["opcode"]=>
- int(149)
- ["opcode_name"]=>
- string(21) "ZEND_HANDLE_EXCEPTION"
- ["flags"]=>
- int(0)
- ["lineno"]=>
- int(1)
- }
- }
- }
parsekit扩展的安装请参见这篇文章
系统缓存
它是指APC把PHP文件源码的编译结果缓存起来,然后在每次调用时先对比时间标记。如果未过期,则使用缓存的中间代码运行。默认缓存3600s(一小时)。但是这样仍会浪费大量CPU时间。因此可以在php.ini中设置system缓存为永不过期(apc.ttl=0)。不过如果这样设置,改运php代码后需要重启WEB服务器。目前使用较多的是指此类缓存。
用户数据缓存
缓存由用户在编写PHP代码时用apc_store和apc_fetch函数操作读取、写入的。如果数据量不大的话,可以一试。如果数据量大,使用类似memcache此类的更加专著的内存缓存方案会更好。
APC模块的安装
最简单的方法是直接使用pecl,在命令行下输入:/usr/local/php/bin/pecl install apc
然后按照提示一步步完成即可,示例如下:
- [root@iZ23bm1tc0pZ ~]# /usr/local/php/bin/pecl install apc
- downloading APC-3.1.13.tgz ...
- Starting to download APC-3.1.13.tgz (171,591 bytes)
- .....................................done: 171,591 bytes
- 55 source files, building
- running: phpize
- Configuring for:
- PHP Api Version: 20100412
- Zend Module Api No: 20100525
- Zend Extension Api No: 220100525
- Enable internal debugging in APC [no] : no
- Enable per request file info about files used from the APC cache [no] : no
- Enable spin locks (EXPERIMENTAL) [no] : no
- Enable memory protection (EXPERIMENTAL) [no] : no
- Enable pthread mutexes (default) [no] : no
- Enable pthread read/write locks (EXPERIMENTAL) [yes] : yes
然后重启服务器即可:
lnmp nginx restart
先看一下没有使用apc情况下的压测结果:
- [root@iZ23bm1tc0pZ ~]# ab -n1000 -c100 http://phpfensi.com/index.php
- This is ApacheBench, Version 2.3 <$Revision: 1706008 $>
- Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.phpfensi.com/
- Licensed to The Apache Software Foundation, http://www.apache.org/
- Benchmarking zfsphp.cn (be patient)
- Completed 100 requests
- Completed 200 requests
- Completed 300 requests
- Completed 400 requests
- Completed 500 requests
- Completed 600 requests
- Completed 700 requests
- Completed 800 requests
- Completed 900 requests
- Completed 1000 requests
- Finished 1000 requests
- Server Software: nginx
- Server Hostname: zfsphp.cn
- Server Port: 80
- Document Path: /index.php
- Document Length: 14341 bytes
- Concurrency Level: 100
- Time taken for tests: 15.517 seconds
- Complete requests: 1000
- Failed requests: 0
- Total transferred: 14544000 bytes
- HTML transferred: 14341000 bytes
- Requests per second: 64.45 [#/sec] (mean)
- Time per request: 1551.671 [ms] (mean)
- Time per request: 15.517 [ms] (mean, across all concurrent requests)
- Transfer rate: 915.34 [Kbytes/sec] received
- Connection Times (ms)
- min mean[+/-sd] median max
- Connect: 0 2 4.8 0 17
- Processing: 46 1481 277.0 1560 1638
- Waiting: 42 1481 277.1 1560 1638
- Total: 58 1482 272.8 1560 1638
- Percentage of the requests served within a certain time (ms)
- 50% 1560
- 66% 1576
- 75% 1582
- 80% 1587
- 90% 1602
- 95% 1612
- 98% 1622
- 99% 1629
- 100% 1638 (longest request)
可见最大吞吐率只有64.45reqs/s,然后我们开启apc,测试结果如下:
- [root@iZ23bm1tc0pZ ~]# ab -n1000 -c100 http://phpfensi.com/index.php
- This is ApacheBench, Version 2.3 <$Revision: 1706008 $>
- Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.phpfensi.com/
- Licensed to The Apache Software Foundation, http://www.apache.org/
- Benchmarking zfsphp.cn (be patient)
- Completed 100 requests
- Completed 200 requests
- Completed 300 requests
- Completed 400 requests
- Completed 500 requests
- Completed 600 requests
- Completed 700 requests
- Completed 800 requests
- Completed 900 requests
- Completed 1000 requests
- Finished 1000 requests
- Server Software: nginx
- Server Hostname: phpfensi.com
- Server Port: 80
- Document Path: /index.php
- Document Length: 14341 bytes
- Concurrency Level: 100
- Time taken for tests: 7.122 seconds
- Complete requests: 1000
- Failed requests: 0
- Total transferred: 14544000 bytes
- HTML transferred: 14341000 bytes
- Requests per second: 140.41 [#/sec] (mean)
- Time per request: 712.189 [ms] (mean)
- Time per request: 7.122 [ms] (mean, across all concurrent requests)
- Transfer rate: 1994.29 [Kbytes/sec] received
- Connection Times (ms)
- min mean[+/-sd] median max
- Connect: 0 1 2.4 0 10
- Processing: 23 677 125.3 705 775
- Waiting: 22 677 125.4 705 775
- Total: 30 678 123.1 705 775
- Percentage of the requests served within a certain time (ms)
- 50% 705
- 66% 719
- 75% 726
- 80% 730
- 90% 742
- 95% 750
- 98% 760
- 99% 765
- 100% 775 (longest request)
[root@iZ23bm1tc0pZ ~]# ab -n1000 -c100 http://phpfensi.com/index.php
- This is ApacheBench, Version 2.3 <$Revision: 1706008 $>
- Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.phpfensi.com/
- Licensed to The Apache Software Foundation, http://www.apache.org/
- Benchmarking zfsphp.cn (be patient)
- Completed 100 requests
- Completed 200 requests
- Completed 300 requests
- Completed 400 requests
- Completed 500 requests
- Completed 600 requests
- Completed 700 requests
- Completed 800 requests
- Completed 900 requests
- Completed 1000 requests
- Finished 1000 requests
- Server Software: nginx
- Server Hostname: phpfensi.com
- Server Port: 80
- Document Path: /index.php
- Document Length: 14341 bytes
- Concurrency Level: 100
- Time taken for tests: 2.263 seconds
- Complete requests: 1000
- Failed requests: 0
- Total transferred: 14544000 bytes
- HTML transferred: 14341000 bytes
- Requests per second: 441.98 [#/sec] (mean)
- Time per request: 226.255 [ms] (mean)
- Time per request: 2.263 [ms] (mean, across all concurrent requests)
- Transfer rate: 6277.49 [Kbytes/sec] received
- Connection Times (ms)
- min mean[+/-sd] median max
- Connect: 0 1 3.1 0 12
- Processing: 18 215 38.1 222 255
- Waiting: 18 215 38.3 222 255
- Total: 26 216 35.6 223 255
- Percentage of the requests served within a certain time (ms)
- 50% 223
- 66% 230
- 75% 232
- 80% 234
- 90% 237
- 95% 239
- 98% 240
- 99% 243
- 100% 255 (longest request)
这一次吞吐率居然达到441.98reqs/s,提高了三倍多,相比最初的64.45reqs/s提高了近7倍,可见使用apc的opcode缓存配合Smarty缓存,对网站性能的优化效果还是相当明显的。
Tags: 缓存 组件 模块
- 上一篇:php系统日志切割的实例
- 下一篇:阿里云直播PHP SDK使用方法详解
相关文章
- ·PHP缓存技术详谈(2013-11-27)
- ·PHP中常用三种缓存技术(2013-11-30)
- ·php header()函数设置页面Cache缓存(2014-01-06)
- ·php禁止页面缓存的代码介绍(2014-01-16)
- ·emlog中使用memcache缓存配置修改方法(2014-06-17)
- ·php 全面禁止浏览器缓存页面内容详解(2014-07-23)
- ·PHP中常用的缓存技术介绍(2014-07-29)
- ·PHP脚本实现Magento权限设置与缓存清理(2014-07-30)
- ·php 缓存技术(2014-08-15)
- ·php中用缓存与不用缓存性能测试(2014-08-27)
- ·php实现memcache缓存实例详解(2014-08-27)
- ·php文件缓存类实例整理(2014-08-27)
- ·php MemCache内存缓存学习笔记(2014-08-27)
- ·清除memcache中的缓存一些方法总结(2014-08-27)
- ·PHP利用memcache缓存技术简单介绍(2014-08-28)
- ·php内存缓存实现程序代码(2014-08-28)
推荐文章
热门文章
最新评论文章
- 写给考虑创业的年轻程序员(10)
- PHP新手上路(一)(7)
- 惹恼程序员的十件事(5)
- PHP邮件发送例子,已测试成功(5)
- 致初学者:PHP比ASP优秀的七个理由(4)
- PHP会被淘汰吗?(4)
- PHP新手上路(四)(4)
- 如何去学习PHP?(2)
- 简单入门级php分页代码(2)
- php中邮箱email 电话等格式的验证(2)