ZendFramework官方提供的性能优化没有实际意义
2012-11-29 17:21
477 查看
昨天把zf的官方性能优化都做了一遍,本来希望官方的性能优化方案能够真正起到优化效果,中间由于bug误以为有效果了,还发了一篇博文,可惜后来一查完全越优化越差了。下面简单吧ZF官方的性能优化说一下,还有最新的(ZF1版,第二版还没有怎么用)ZF1.12中添加的autoload_classmap的机制,设计cache的部分就不提了,那个减少了代码的执行逻辑,性能提升是肯定的(还需要对比缓存获取过程和减少的代码逻辑执行的时间差,提升不绝对)。
官方优化如下:
1、在include_path的路径中使用绝对路径,这样可以使用php的realpath cache
While this may seem a micro-optimization, the fact is that if you don't, you'll get very little benefit from PHP's
realpath cache, and as a result, opcode caching will not perform nearly as you may expect.
2、减少include_path的路径定义,定义ZF在include_path的前面,将当前目录放在最后或者不使用当前目录,这样可以加快文件查找的速度。
Include paths are scanned in the order in which they appear in the include_path. Obviously, this means that you'll get a result faster if the file is found
on the first scan rather than the last. Thus, a rather obvious enhancement is to simply reduce the number of paths in your include_path to only what you need. Look through each include_path you've defined, and determine if you actually have any functionality
in that path that is used in your application; if not, remove it.
目的是为了加快文件查找过程,觉得这点不够好,最好是所有文件都使用绝对地址加载不要查找,浪费这个时间做什么啊
3、减少不需要的require_once,完全使用autoload和require加载,官方提供了一个shell来删除require_once
% cd path/to/ZendFramework/library
% find . -name '*.php' -not -wholename '*/Loader/Autoloader.php' \
-not -wholename '*/Application.php' -print0 | \
xargs -0 sed --regexp-extended --in-place 's/(require_once)/\/\/ \1/g'
这个效果还是比较明显的,要求你写程序要符合规范要让加载器能够找到你的文件并加载,要不然你就麻烦了。
另外,最好都使用require或include,不要加once,原因看http://www.laruence.com/2012/09/12/2765.html;
使用apc的用户,在产品上线后可以把apc的stat设置为0,不让它检查文件修改,这样也可以获得性能提升,更新文件可以自己写程序清理下缓存
4、加快插件加载,使用一个include文件将常用插件放在文件中
个人感觉这个行为的过程就是把每次单独加载的过程改成一次完成,然后依靠apc等缓存来提速,这个的作用真不明显
5、使用自动加载器Zend_Loader_ClassMapAutoloader
这个确实没有怎么感觉到提升,个人认为即使加了这个也不能解决ZF过于臃肿的问题,优化本身就有限制。
这里给个添加的方法,有兴趣的朋友可以试试,以下部分内容来自上次误写的一篇博文。
加载器的使用:
在ZF1.12的目录中有一个bin目录下面有加载器类需要的classmap文件创建程序classmap_generator.php,通过这个创建器我们可以对相应目录下的类进行classmap文件生成,生成文件默认是在指定的class目录下的,也就是说都是基于你给创建器指定的目录的,也可以通过-o or --output 来指定。
在进行生成classmap生成前最好看下创建器的帮助,使用php classmap_generator.php -h,打印有如下信息:
Usage: classmap_generator.php [ options ]
--help|-h Get usage message
--library|-l [ <string> ] Library to parse; if none provided, assumes current directory
--output|-o [ <string> ] Where to write autoload file; if not provided, assumes "autoload_classmap.php" in library directory
--overwrite|-w Whether or not to overwrite existing autoload file
然后就可以使用,例如:php classmap_generator.php -l /data/www/library, 执行完就可以看到映射文件了。
接下来就要使用加载器了,可以看到Zend_Loader_ClassMapAutoloader文件里面提供了register,autoload方法,通过这个方法可以直接使用加载器,提醒,这里需要一个前提,如果你先前没有使用其他加载器,这里可以直接使用,如果先前有使用,比如我自己就一直使用Zend_Loader_Autoloader,并注册了一些命名空间,这样使用的时候就会有问题,如果映射文件包含所有加载的类,可以去掉原来的加载器直接使用,如果不是这样,保险起见可以把类映射加载器作为Zend_Loader_Autoloader的一个回调就好了,如下:
require_once LIB_DIR
. 'Zend/Loader/ClassMapAutoloader.php';
[align=left]$loader_map = new Zend_Loader_ClassMapAutoloader();[/align]
$loader_map->registerAutoloadMaps( array(LIB_DIR
. 'autoload_classmap.php' , APP_DIR . 'models' .
DIRECTORY_SEPARATOR . 'autoload_classmap.php' ));
require_once LIB_DIR
. 'Zend/Loader/Autoloader.php';
[align=left]$loader = Zend_Loader_Autoloader::getInstance();[/align]
[align=left]$loader->unshiftAutoloader(array($loader_map, 'autoload' ));[/align]
然后把注册的命名空间去掉,就可以使用了。
测试下效果
硬件环境
CPU: Intel(R) Xeon(R) CPU E5620
mem: 4G used 2.4 free 1.3
软件环境
nginx 1.2.4 php 5.3.17
不使用类加载器:
Concurrency Level: 40
Time taken for tests: 0.811 seconds
Complete requests: 100
Failed requests: 0
Write errors: 0
Total transferred: 449700 bytes
HTML transferred: 437600 bytes
Requests per second: 123.29 [#/sec] (mean)
Time per request: 324.432 [ms] (mean)
Time per request: 8.111 [ms] (mean, across all concurrent requests)
Transfer rate: 541.45 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 2 1.4 2 14
Processing: 47 253 81.3 280 343
Waiting: 44 253 81.4 280 343
Total: 48 255 81.2 282 344
Percentage of the requests served within a certain time (ms)
50% 282
66% 292
75% 308
80% 318
90% 333
95% 336
98% 344
99% 344
100% 344 (longest request)
使用大文件(72K)同时使用类加载器:
Concurrency Level: 40
Time taken for tests: 0.831 seconds
Complete requests: 100
Failed requests: 0
Write errors: 0
Total transferred: 449700 bytes
HTML transferred: 437600 bytes
Requests per second: 120.32 [#/sec] (mean)
Time per request: 332.433 [ms] (mean)
Time per request: 8.311 [ms] (mean, across all concurrent requests)
Transfer rate: 528.42 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 1 1.5 1 15
Processing: 46 258 79.0 300 334
Waiting: 45 258 79.0 299 334
Total: 48 260 78.9 301 335
Percentage of the requests served within a certain time (ms)
50% 301
66% 307
75% 311
80% 313
90% 314
95% 322
98% 330
99% 335
100% 335 (longest request)
可以看到和原来情况差不多,究其原因,个人通过跟踪php-fpm的进程过程,发现文件本身的加载在ZF中已经达到160个文件以上了,这个classmap不能减少这个操作,只能说是应用了官方优化的第一条,这个不能解决框架本身的性能瓶颈。对比下yii包含的文件数60个,这个就是性能差距的根本。
资料:
http://talks.php.net/show/froscon08/0
http://framework.zend.com/manual/1.12/en/performance.html
http://yiiframework.com/
官方优化如下:
1、在include_path的路径中使用绝对路径,这样可以使用php的realpath cache
While this may seem a micro-optimization, the fact is that if you don't, you'll get very little benefit from PHP's
realpath cache, and as a result, opcode caching will not perform nearly as you may expect.
2、减少include_path的路径定义,定义ZF在include_path的前面,将当前目录放在最后或者不使用当前目录,这样可以加快文件查找的速度。
Include paths are scanned in the order in which they appear in the include_path. Obviously, this means that you'll get a result faster if the file is found
on the first scan rather than the last. Thus, a rather obvious enhancement is to simply reduce the number of paths in your include_path to only what you need. Look through each include_path you've defined, and determine if you actually have any functionality
in that path that is used in your application; if not, remove it.
目的是为了加快文件查找过程,觉得这点不够好,最好是所有文件都使用绝对地址加载不要查找,浪费这个时间做什么啊
3、减少不需要的require_once,完全使用autoload和require加载,官方提供了一个shell来删除require_once
% cd path/to/ZendFramework/library
% find . -name '*.php' -not -wholename '*/Loader/Autoloader.php' \
-not -wholename '*/Application.php' -print0 | \
xargs -0 sed --regexp-extended --in-place 's/(require_once)/\/\/ \1/g'
这个效果还是比较明显的,要求你写程序要符合规范要让加载器能够找到你的文件并加载,要不然你就麻烦了。
另外,最好都使用require或include,不要加once,原因看http://www.laruence.com/2012/09/12/2765.html;
使用apc的用户,在产品上线后可以把apc的stat设置为0,不让它检查文件修改,这样也可以获得性能提升,更新文件可以自己写程序清理下缓存
4、加快插件加载,使用一个include文件将常用插件放在文件中
个人感觉这个行为的过程就是把每次单独加载的过程改成一次完成,然后依靠apc等缓存来提速,这个的作用真不明显
5、使用自动加载器Zend_Loader_ClassMapAutoloader
这个确实没有怎么感觉到提升,个人认为即使加了这个也不能解决ZF过于臃肿的问题,优化本身就有限制。
这里给个添加的方法,有兴趣的朋友可以试试,以下部分内容来自上次误写的一篇博文。
加载器的使用:
在ZF1.12的目录中有一个bin目录下面有加载器类需要的classmap文件创建程序classmap_generator.php,通过这个创建器我们可以对相应目录下的类进行classmap文件生成,生成文件默认是在指定的class目录下的,也就是说都是基于你给创建器指定的目录的,也可以通过-o or --output 来指定。
在进行生成classmap生成前最好看下创建器的帮助,使用php classmap_generator.php -h,打印有如下信息:
Usage: classmap_generator.php [ options ]
--help|-h Get usage message
--library|-l [ <string> ] Library to parse; if none provided, assumes current directory
--output|-o [ <string> ] Where to write autoload file; if not provided, assumes "autoload_classmap.php" in library directory
--overwrite|-w Whether or not to overwrite existing autoload file
然后就可以使用,例如:php classmap_generator.php -l /data/www/library, 执行完就可以看到映射文件了。
接下来就要使用加载器了,可以看到Zend_Loader_ClassMapAutoloader文件里面提供了register,autoload方法,通过这个方法可以直接使用加载器,提醒,这里需要一个前提,如果你先前没有使用其他加载器,这里可以直接使用,如果先前有使用,比如我自己就一直使用Zend_Loader_Autoloader,并注册了一些命名空间,这样使用的时候就会有问题,如果映射文件包含所有加载的类,可以去掉原来的加载器直接使用,如果不是这样,保险起见可以把类映射加载器作为Zend_Loader_Autoloader的一个回调就好了,如下:
require_once LIB_DIR
. 'Zend/Loader/ClassMapAutoloader.php';
[align=left]$loader_map = new Zend_Loader_ClassMapAutoloader();[/align]
$loader_map->registerAutoloadMaps( array(LIB_DIR
. 'autoload_classmap.php' , APP_DIR . 'models' .
DIRECTORY_SEPARATOR . 'autoload_classmap.php' ));
require_once LIB_DIR
. 'Zend/Loader/Autoloader.php';
[align=left]$loader = Zend_Loader_Autoloader::getInstance();[/align]
[align=left]$loader->unshiftAutoloader(array($loader_map, 'autoload' ));[/align]
然后把注册的命名空间去掉,就可以使用了。
测试下效果
硬件环境
CPU: Intel(R) Xeon(R) CPU E5620
mem: 4G used 2.4 free 1.3
软件环境
nginx 1.2.4 php 5.3.17
不使用类加载器:
Concurrency Level: 40
Time taken for tests: 0.811 seconds
Complete requests: 100
Failed requests: 0
Write errors: 0
Total transferred: 449700 bytes
HTML transferred: 437600 bytes
Requests per second: 123.29 [#/sec] (mean)
Time per request: 324.432 [ms] (mean)
Time per request: 8.111 [ms] (mean, across all concurrent requests)
Transfer rate: 541.45 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 2 1.4 2 14
Processing: 47 253 81.3 280 343
Waiting: 44 253 81.4 280 343
Total: 48 255 81.2 282 344
Percentage of the requests served within a certain time (ms)
50% 282
66% 292
75% 308
80% 318
90% 333
95% 336
98% 344
99% 344
100% 344 (longest request)
使用大文件(72K)同时使用类加载器:
Concurrency Level: 40
Time taken for tests: 0.831 seconds
Complete requests: 100
Failed requests: 0
Write errors: 0
Total transferred: 449700 bytes
HTML transferred: 437600 bytes
Requests per second: 120.32 [#/sec] (mean)
Time per request: 332.433 [ms] (mean)
Time per request: 8.311 [ms] (mean, across all concurrent requests)
Transfer rate: 528.42 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 1 1.5 1 15
Processing: 46 258 79.0 300 334
Waiting: 45 258 79.0 299 334
Total: 48 260 78.9 301 335
Percentage of the requests served within a certain time (ms)
50% 301
66% 307
75% 311
80% 313
90% 314
95% 322
98% 330
99% 335
100% 335 (longest request)
可以看到和原来情况差不多,究其原因,个人通过跟踪php-fpm的进程过程,发现文件本身的加载在ZF中已经达到160个文件以上了,这个classmap不能减少这个操作,只能说是应用了官方优化的第一条,这个不能解决框架本身的性能瓶颈。对比下yii包含的文件数60个,这个就是性能差距的根本。
资料:
http://talks.php.net/show/froscon08/0
http://framework.zend.com/manual/1.12/en/performance.html
http://yiiframework.com/
相关文章推荐
- 【转】 luajit官方性能优化指南和注解
- ASP.NET MVC性能优化(实际项目中)
- android app性能优化大汇总(google官方Android性能优化典范 - 第2季)
- Unity3D -- 性能优化(3)(官方教程Optimizing garbage collection in Unity games翻译)
- tomcat 性能优化(根据自己实际情况配置)
- 【转】记一次ASP.NET MVC性能优化(实际项目中)
- Unity3D -- 性能优化(4)(官方教程Optimizing graphics rendering in Unity games翻译)
- SQL点滴22—性能优化没有那么神秘
- 在开发中你可能没有考虑到的两个性能优化
- Flash 平台应用性能优化官方文档
- luajit官方性能优化指南和注解
- 在开发中你可能没有考虑到的两个性能优化
- Unity性能优化(1)-官方教程The Profiler window翻译
- web前端性能意义、关注重点、测试方案、优化技巧
- Unity性能优化(2)-官方教程Diagnosing performance problems using the Profiler window翻译
- 性能优化官方文档阅读笔记
- android app性能优化大汇总(google官方Android性能优化典范 - 第1季)
- SQL点滴22—性能优化没有那么神秘
- android app性能优化大汇总(google官方Android性能优化典范 - 第3季)
- Google官方 详解 Android 性能优化二【史诗巨著之内存篇】