About

php性能优化

降低io消耗

  • 缓存代码文件

  • 预编译所有文件

Session存储

文件存储不是一个优秀的方案

  • mm – 固话的共享内存存储

  • apc – 用APC存储、获取、删除(apc存储session会有问题,不建议使用)

  • memcache – 基于内存的存储服务

    session.save_handler = mm

    session.save_handler = memcache

若服务器运行在linux上,可修改session的存储目录

session.save_path = /dev/shm

/dev/shm是Linux系统独有的TMPFS文件系统,是以内存为主要存储方式的文件系统,比RAMDISK更优秀,因为可以使用DISKSWAP作为补充,而且是系统自带的功能模块,不需要另行配置

使用php加速器

  • Zend OPcache

  • apc

  • eAccelerator

  • XCache

根据需要合理使用user cache

避免重复计算

1
for($i=0;$i<getTotal();$i++) //getTotal没有必要被重复调用

为静态文件选择更好的server

虽然apache是很强大的动态语言服务器,但静态请求可以通过其他一些webserver很好的支持。
比如: lighttpd / Boa / Tux / thttpd
上述webserver在服务于静态内容请求时,响应速度要比apache1或apache2快300~400%倍

分析瓶颈

xdebug 配合 qcachegrind 分析瓶颈

减少路由查找

尽量使用绝对路径

尽可能的用绝对路径,相对路径虽然简短但会产生额外的寻径开销。而且使用绝对路径也很保险
少用require_once

减少查找开销
少用魔法函数

get() | set() | autoload() | call()

比如,我们的:

1
$this->apiProxy->page->page_id;//__call增加了符号表查找的时间

修复报错

每一个报错,会带来性能影响:

  • 产生一个复杂的错误字符串
  • 产生一个标准输出
  • 可能会产生一个日志文件的写操作或者syslog的写操作

少用@

不方便调试 && 低效

合理运用字符串比较函数

strncmp / strncasecmp 要比 substr 快

不要随便就复制变量

有时候为了使 PHP 代码更加整洁,一些 PHP 新手(包括我)会把预定义好的变量复制到一个名字更简短的变量中,其实这样做的结果是增加了一倍的内存消耗,只会使程序更加慢。试想一下,在下面的例子中,如果用户恶意插入 512KB 字节的文字到文本输入框中,这样就会导致 1MB 的内存被消耗!

BAD:

1
2
$description = $_POST['description'];
echo $description;

GOOD:

1
echo $_POST['description'];

对字符串使用单引号

PHP 引擎允许使用单引号和双引号来封装字符串变量,但是这个是有很大的差别的!使用双引号的字符串告诉 PHP 引擎首先去读取字符串内容,查找其中的变量,并改为变量对应的值。一般来说字符串是没有变量的,所以使用双引号会导致性能不佳。最好是使用字符串连接而不是双引号字符串。

BAD:

1
2
$type = "mixed";
$output = "This is a $type string";

GOOD:

1
2
$type = 'mixed';
$output = 'This is a ' . $type .' string';

不要在 echo 中使用连接符

很多 PHP 程序员(有包括我)不知道在用 echo 输出多个变量的时候,其实可以使用逗号来分开的,而不必用字符串先把他们先连起来,如下面的第一个例子中,由于使用了连接符就会有性能问题,因为这样就会需要 PHP 引擎首先把所有的变量连接起来,然后在输出,而在第二个例子中,PHP 引擎就会按照循序输出他们。

BAD:

1
echo 'Hello, my name is' . $firstName . $lastName . ' and I live in ' . $city;

GOOD:

1
echo 'Hello, my name is' , $firstName , $lastName , ' and I live in ' , $city;

使用 switch/case 代替 if/else

对于只有单个变量的判断,使用 switch/case 语句而不是 if/else 语句,会有更好的性能,并且代码更加容易阅读和维护。

BAD:

1
2
3
4
5
6
7
8
9
if($_POST['action'] == 'add') {
addUser();
} elseif ($_POST['action'] == 'delete') {
deleteUser();
} elseif ($_POST['action'] == 'edit') {
editUser();
} else {
defaultAction();
}

GOOD:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
switch($_POST['action']) {
case 'add':
addUser();
break;
case 'delete':
deleteUser();
break;
case 'edit':
editUser();
break;
default:
defaultAction();
break;
}

压缩

大多数的浏览器均支持内容解压缩 平均能压缩页面的60~80%
Apache1 采用mod_gzip / mod_deflate
Apache2 采用 mod_deflate
PHP 通过设置配置文件中 zlib.output_compression=1 或者在代码中使用 ob_start(“ob_gzhandler”) 压缩内容

压缩一般要额外消耗3~5%的CPU(是否开启压缩,还需要根据情况而定)

C和C++中Const 修饰指针

C、C++中Const修饰指针时总是记不住到底作用的是指针还是指针指向的变量内容:

最近总结了一个绝招,可以绝对理清楚!那就是就近原则

所谓就近原则,意思就是const靠哪个近,就作用在那个上面.

const靠int类型关键字近,那就是说修饰的是整形变量;const靠指针变量名近,那就是说修饰该指针,说明它不是指针变量,而是指针常量;;

但是有一个问题:既然说到是const修饰指针,那就一定有如 char const * pContent; 那这个const在*和变量名之间,到底靠谁近呢?

这里要解释说明的是:const靠谁近指的是类型(如int、char等)和变量名(如这里的pContent),不能算*,因此这里const当然靠char近,所以pContent是一个指向字符常量的指针;

有了这一条就近原则,const问题迎刃而解!;

1) const在前面;

1
2
3
4
5
6
7
8
9
10
const int nValue; //nValue是const
const char *pContent; //*pContent是const, pContent可变
const (char *) pContent; //pContent是const,*pContent可变
char* const pContent; //pContent是const,*pContent可变
const char* const pContent; //pContent和*pContent都是const

2) const在后面,与上面的声明对等

1
2
3
4
5
6
7
8
9
10
int const nValue; // nValue是const
char const * pContent;// *pContent是const, pContent可变
(char *) const pContent;//pContent是const, *pContent可变
char* const pContent;// pContent是const, *pContent可变
char const* const pContent;// pContent和*pContent都是const;

=================================================================================;

Bjarne在他的The C++ Programming Language里面给出过一个助记的方法: 把一个声明从右向左读。;

char const cp;;( 读成 pointer to );

cp is a const pointer to char :cp是一个指向字符型的常量指针,指针不能改变;;

const char * p;;

p is a pointer to const char:cp是一个指向字符型常量的指针,指针指向的值不能随便改变;;

char const * p; 同上。;

url:http://guhanjie.iteye.com/blog/1683154