340 likes | 529 Views
PHP 代码优化小技巧 PHP 扩展基础及实践 Apache 模块开发实践 夏学锋 ( Mail: mail@xuefeng.org). 大并发访问下的优化. 调优业务逻辑 ( 简化 / 拆分业务逻辑 ) 缓存访问量大的数据 ( 文件 / 内存 / Memcache ) 优化 / 压缩输出内容 ( css / j s / html / ob_start ()) 优化数据结构 ( database ) 缓存加速 PHP 代码 ( APC / Zend Optimizer / XCache ).
E N D
PHP 代码优化小技巧 • PHP 扩展基础及实践 • Apache模块开发实践夏学锋(Mail: mail@xuefeng.org)
大并发访问下的优化 • 调优业务逻辑 ( 简化 / 拆分业务逻辑 ) • 缓存访问量大的数据 ( 文件 / 内存 / Memcache ) • 优化 / 压缩输出内容 ( css / j s / html / ob_start()) • 优化数据结构 (database ) • 缓存加速 PHP 代码 ( APC / Zend Optimizer / • XCache )
PHP 代码优化 合理使用静态方法提高执行效率 50%
PHP 代码优化 尽量少用@操作符
PHP 代码优化 代码简短并不一定高效
PHP 代码优化 • 对纯文本文件或不需要 PHP 进行解析文件的读取并输出 • file_get_contents / file • fread / fgets • require / include / require_once / include_once • readfile • fpassthru • 应用范围: • 文件下载 / 包含静态(缓存)文件 / 读取配置文件 等 • 优化方法: • 理解每个函数的运行过程,有针对性的使用相关函数
PHP 代码优化 • readfile 和 fpassthru 直接调用 php_stream_passthru 将文件读到内存中 • fgets / file / file_get_contents 调用 php_stream_open_wrapper_* 封装函数 • include / require 调用 zend_stream_open ()
PHP 变量结构(Zend/zend.h) 保存变量值 被引用的次数 变量的类型 是否为引用
PHP 变量结构(Zend/zend.h) 保存变量值 被引用的次数 变量的类型 是否为引用
PHP 变量结构(Zend/zend.h) 8 bytes ? 4 bytes 1 bytes 1 bytes
PHP 变量结构(Zend/zend.h) 8 bytes 16bytes 4 bytes 1 bytes 1 bytes
如何创建一个变量 <?php $a = 123; $b = “123”; $c = array( 5=>”a”, “a”=>10 ); ?> zval *a; MAKE_STD_ZVAL(a); ZVAL_LONG(a, 123); ZEND_SET_SYMBOL(EG(active_symbol_table), "a", a); zval *b; MAKE_STD_ZVAL(b); ZVAL_STRING(b, “123”, 1); // 参数1指定自动分配空间ZEND_SET_SYMBOL(EG(active_symbol_table), "b", b); zval *c; MAKE_STD_ZVAL(c); array_init(c); add_index_string(c, 5, "a", 1); add_assoc_long(c, "a", 10);ZEND_SET_SYMBOL(EG(active_symbol_table), “c", c);
如何传递参数 function hello($a, $b = “world”) { echo $a . $b; } PHP_FUNCTION(hello) { char *a, *b = “world”; int a_len, b_len = sizeof(“world”) – 1; if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &a, &a_len, &b, &b_len)) { PHPWRITE(a, a_len); PHPWRITE(b, b_len); } } 所有 | 以后的都为可选参数
如何返回值 function my_func($a, $b) { return $a + $b; } PHP_FUNCTION(my_func) { zval *a, *b; if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &a, &b)) { convert_to_long(a); convert_to_long(b); return_value->type = IS_LONG; return_value->value.lval = a->value.lval + b->value.lval; return; }} 类型转换
实例(域名信息查询) 获取域名信息服务主服务器地址: http://www.iana.org/root-whois/
实例(域名信息查询) 连接 Server (43) 发送查询 接收信息 检查返回信息 发现完整信息 服务器地址,跳到步骤 1. 查询结果,构造 返回结果返回 Userland.
实例(域名信息查询) server_list.h 所有域名信息服务主服务器地址 php_whois.h扩展头文件 whois.c 扩展主程序文件 whois.php 测试文件
实例(域名信息查询) 查询是一个正常的域名或 IP地址 ?
实例(域名信息查询) 查询是一个正常的域名或 IP地址 ? 从域名后缀提取主域名服务器地址
实例(域名信息查询) 查询是一个正常的域名或 IP地址 ? 从域名后缀提取主域名服务器地址 详细信息在别的域名信息服务器上
实例(域名信息查询) 查询是一个正常的域名或 IP地址 ? 从域名后缀提取主域名服务器地址 详细信息在别的域名信息服务器上 调用Socket 进域名信息服务器通讯
实例(域名信息查询) 查询是一个正常的域名或 IP地址 ? 从域名后缀提取主域名服务器地址 详细信息在别的域名信息服务器上 调用Socket 进域名信息服务器通讯 Userland 接口
实例(域名信息查询) Socket 工作模式: 阻塞模式 | 非阻塞模式 | I/O多路复用 | 信号驱动I/O |异步I/O (避免堵塞)
实例(域名信息查询) 返回结果为 Array() 时超
欢迎大家讨论 ?
Apache APR模块 目标: 在 Apache 扩展为依托记录指定文件的点击次数 关键词: IPC Shared memory 内存消耗: 每个 文件被 Hash 后只有4个字节( i386 ), 假定10000个文件 10000 * 4 / 1024 = 39.1 Kbytes 性能消耗: 通常在 PHP 等脚本中写 DB / 文件 / Memcache来记录点击次数 它的性能和 Apache 的 access_log 相比还是有差距的,而 Apache 写日志要对文件进行操作,与读写内存操作的 Apache 模块来说性 价比又是一个差距。 注: APR 是 Apache portable runtime 的简写
Apache APR模块 Apache 运行期间与模块的交互
Apache APR模块 模块编写: 1. 注册一个 Apache module, 类型为所有module完成 后再调用此module(APR_HOOK_LAST)2. 对每个访问的URI进行过虑, 符合指定记录类型的文件 就进行统计(类型由httpd.conf中设定)3. 统计开始时挂载共享内存, 第一次挂载的时候共享内存 不存在, 需要向Apache申请共享内存空间.4. 循环共享内存中的数据, 如果请求URI的key和共享内存 中已保存的某条记录相匹配, 则将该key的计数器累加5. 从当前进程空间中卸载挂进来的共享内存空间6. 模块返回“不做任何处理”的代码(return DECLINED)
Apache APR模块 访问的文件不存在 循环统计队列中的文件列表,找到 Hash Key 就将该 Key 的 acc 累加 1,未找到则将该 Hash 添加到队列中. 当队列中的所有的文件被点击 N 次之后会将队列中的数据写入磁盘文件,重置队列中所有 Hash 的累加器为 0
Apache APR模块 队列中所有文件访问次数之和 文件的 Hash key
欢迎大家讨论 ?
相关资源 相关 文件放在 http://code.google.com/p/php-whois
谢谢 夏学锋 mail@xuefeng.org