The content of this article is to share with you some suggestions on improving PHP efficiency and optimization. It has a certain reference value. Friends in need can refer to it
1 String
1.1 Use less regular expressions
If you can use PHP’s internal string manipulation functions, try to use them instead of regular expressions. Because its efficiency is higher than regular.
It goes without saying that regular expressions consume the most performance.
The str_replace function is much faster than preg_replace, and the strtr function is faster than str_replace.
Are there any useful functions that you missed?
For example: strpbrk(), strncasecmp(), strpos(), strrpos(), stripos(), strripos().
1.2 Character replacement
If all that needs to be converted is a single character, use a string as the strtr() function to complete the replacement instead of an array:
$addr = strtr($addr, "abcd", "efgh"); // Recommended
$addr = strtr($addr, array('a' => 'e', )); // Not recommended
Efficiency improvement: 10 times .
str_replace character replacement is faster than regular replacement preg_replace, but strtr is 1/4 faster than str_replace.
In addition, do not make unnecessary substitutions. Even if there is no substitution, str_replace will allocate memory for its parameters. very slow!
Use strpos to search first (very fast) to see if it needs to be replaced, and if so, replace it.
If replacement is required, the efficiency is almost equal, and the difference is about 0.1%.
If no replacement is required: using strpos is 200% faster.
1.3 Compress large strings
Use gzcompress() and gzuncompress() to compress and decompress large-capacity strings, and then store and retrieve them from the database.
This built-in function uses the gzip algorithm and can compress strings by 90%.
1.4 echo output
echo It is faster to use commas instead of dot connectors in strings.
Although, echo is a language structure, not a real function.
However, it can pass multiple strings separated by commas as "function" parameters, so it will be faster.
echo $str1, $str2; // Fast
echo $str1 . $str2; // Slightly slower
1.5 Try to use single quotes
PHP The engine allows the use of single quotes and double quotes to encapsulate string variables, but their speeds are very different!
Using double quotes in a string will tell the PHP engine to first read the string content, find the variables in it, and change them to the values corresponding to the variables.
Generally speaking, strings have no variables, and using double quotes will lead to poor performance.
It is better to use string concatenation instead of double quoted strings.
$output = "This is a plain string"; // 不好的实践 $output = 'This is a plain string'; // 好的实践 $type = "mixed"; // 不好的实践 $output = "This is a $type string"; $type = 'mixed'; // 好的实践 $output = 'This is a ' . $type . ' string';
1.6 Use isset instead of strlen
When checking the length of a string, our first thought is to use the strlen() function.
This function executes quite quickly because it does not do any calculations and just returns the known string length stored in the zval structure (C's built-in data structure used to store PHP variables).
However, since strlen() is a function, it will be somewhat slow, because the function call will go through many steps, such as lowercase letters and hash search, and will be executed together with the called function.
In some cases, you can use the isset() technique to speed up the execution of your code. For example:
if (strlen($foo) < 5) { echo "Foo is too short"; } // 使用isset() if (!isset($foo{5})) { echo "Foo is too short"; }
1.7 Use split to split a string
When splitting a string, split() is faster than explode().
split()
0.001813 - 0.002271 seconds (avg 0.002042 seconds)
explode()
0.001678 - 0.003626 seconds (avg 0.002652 seconds)
1.8 Echo is more efficient than print
Because echo has no return value and print returns an integer.
Note: When echo outputs large strings, if there is no adjustment, performance will be seriously affected.
Turn on Apache's mod_deflate for compression, or turn on ob_start to put the content into the buffer, which can improve performance issues.
2 Statement
2.1 最好不用@
用@掩盖错误会降低脚本运行速度,并且在后台有很多额外操作。
用@比起不用,效率差距 3 倍。特别不要在循环中使用@。
在 5 次循环的测试中,即使是先用error_reporting(0)关掉错误,循环完成后再打开,都比用@快。
2.2 避免使用魔术方法
对于__开头的函数就命名为魔术函数,它们都在特定的条件下触发。
这些魔术函数包括:__construct()、__get()、__call()、__autoload()等等。
以__autoload() 为例,如果不能将类名与实际的磁盘文件对应起来,将不得不做大量的文件存在判断。
而判断文件存在需要磁盘I/O操作,众所周知,磁盘I/O操作的效率很低,因此这才是使得autoload机制效率降低的原因。
因此,在系统设计时,需要定义一套清晰的、将类名与实际磁盘文件映射的机制。
这个规则越简单越明确,__autoload()机制的效率就越高。
autoload机制并不是天然的效率低下,只有滥用autoload、设计不好的自动装载函数,才会导致其效率的降低.
所以说,尽量避免使用__autoload等魔术方法,有待商榷。
2.3 别在循环里用函数
例如:
for($x=0; $x < count($array); $x++) { }
这种写法在每次循环的时候都会调用 count() 函数,效率大大降低,建议这样:
$len = count($array); for($x=0; $x < $len; $x++) { }
让函数在循环外面一次获得循环次数。
2.4 使用三元运算符
在简单的判断语句中,三元运算符?:更简洁高效。
2.5 使用选择分支语句
switch、case好于使用多个if、else if语句,并且代码更加容易阅读和维护。
2.6 屏蔽敏感信息
使用 error_reporting() 函数来预防潜在的敏感信息显示给用户。
理想的错误报告应该被完全禁用在php.ini文件里
如果用的是共享虚拟主机,php.ini不能修改,最好添加 error_reporting() 函数。
放在每个脚本文件的第一行,或者用require_once()来加载,能有效的保护敏感的SQL查询和路径,在出错时不被显示。
2.7 不实用段标签
不要使用开始标志的缩写形式,你正在使用这样的符号吗,应该用完整的当然,如果是输出变量,用= $value ?>这种方式是鼓励的,可以是代码更加简洁。
2.8 纯PHP代码不加结束标记
如果文件内容是纯 PHP 代码,最好在文件末尾删除 PHP 结束标记?>。
这可以避免在 PHP 结束标记之后万一意外加入了空格或者换行符,会导致 PHP 开始输出这些空白,而脚本中此时并无输出的意图。
2.9 永远不要使用register_globals和magic quotes
这是两个很古老的功能,在当时(十年前)也许是一个好方法,但现在看来并非如此。
老版本的PHP在安装时会默认打开这两个功能,这会引起安全漏洞、编程错误及其他的问题。
如只有用户输入了数据时才会创建变量等。
PHP5.4.0开始这两个功能都被舍弃了,所以每个程序员都应该避免使用。
如果你过去的程序有使用这两项功能,那就尽快将其剔除吧。
3 函数
3.1 尽量使用PHP内部函数
内置函数使用C语言实现,并且经过PHP官方优化,效率更高。
3.2 使用绝对路径
在include和require中尽量使用绝对路径。
如果包含相对路径,PHP会在include_path里面遍历查找文件。
用绝对路径就会避免此类问题,解析路径所需的时间会更少。
3.3 包含文件
尽量不要用require_once和include_once包含文件,它们多一个判断文件是否被引用的过程,能不用尽量不用。
而使用require、include方法代替。
鸟哥在其博客中就多次声明,尽量不要用require_once和include_once。
3.4 函数快于类方法
调用只有一个参数、并且函数体为空的函数,花费的时间等于7-8次$localvar++运算。
而同一功能的类方法大约为15次$localvar++运算。
3.5 用子类方法
基类里面只放能重用的方法,其他功能尽量放在子类中实现,子类里方法的性能优于在基类中。
3.6 类的性能和其方法数量没有关系
新添加10个或多个方法到测试的类后,性能没什么差异。
3.7 读取文件内容
在可以用file_get_contents()替代file()、fopen()、feof()、fgets()等系列方法的情况下,尽量用file_get_contents()。
因为他的效率高得多!
3.8 引用传递参数
通过参数地址引用的方式,实现函数多个返回值,这比按值传递效率高。
方法是在参数变量前加个 &。
3.9 方法不要细分得过多
仔细想想你真正打算重用的是哪些代码?
3.10 尽量静态化
如果一个方法能被静态,那就声明它为静态的,速度可提高1/4,甚至我测试的时候,这个提高了近三倍。
当然了,这个测试方法需要在十万级以上次执行,效果才明显。
其实,静态方法和非静态方法的效率主要区别在内存。
静态方法在程序开始时生成内存,实例方法(非静态方法)在程序运行中生成内存。
所以,静态方法可以直接调用,实例方法要先成生实例再调用,静态速度很快,但是多了会占内存。
任何语言都是对内存和磁盘的操作,至于是否面向对象,只是软件层的问题,底层都是一样的,只是实现方法不同。
静态内存是连续的,因为是在程序开始时就生成了,而实例方法申请的是离散的空间,所以当然没有静态方法快。
静态方法始终调用同一块内存,其缺点就是不能自动进行销毁,而实例化可以销毁。
3.11 用C扩展方式实现
If there are a large number of time-consuming functions in your code, consider implementing them as C extensions.
4 Variables
4.1 Destroy variables in time
Arrays, objects and GLOBAL variables occupy special memory in PHP. This is due to PHP Caused by the underlying zend engine.
Generally speaking, the memory utilization of PHP arrays is only 1/10.
In other words, an array with 100M of memory in C language requires 1G in PHP.
Especially, in systems where PHP is used as a backend server, the problem of excessive memory consumption often occurs.
4.2 Using the $_SERVER variable
If you need to get the script execution time, $_SERVER['REQUSET_TIME'] is better than time().
One is ready-made and can be used directly, and the other requires the result obtained by the function.
4.3 Establishing local variables in methods
It is fastest to create local variables in class methods, almost as fast as calling local variables in methods.
4.4 Local variables are faster than global variables
Because local variables are stored on the stack.
When the stack space occupied by a function is not very large, it is very likely that all this memory will hit the cache, and the efficiency of CPU access is very high.
On the contrary, if a function uses global variables and local variables at the same time, when the difference between the two addresses is large, the CPU cache needs to switch back and forth, and the efficiency will decrease.
4.5 Local variables instead of object properties
Creating an object property (a variable in a class, for example: $this->prop) is 3 times slower than a local variable.
4.6 Declare local variables in advance
Creating an undeclared local variable is 9-10 times slower than creating an already defined local variable.
4.7 Declare global variables with caution
Declaring a global variable that has not been used by any function will also reduce performance.
This is the same as declaring the same number of local variables. PHP may check whether the global variable exists.
4.8 Using $i to increment
When executing the increment or decrement of variable $i, $i will be slower than $i.
This difference is specific to PHP and does not apply to other languages, so please don't modify your C or Java code and expect it to be instantly faster, it won't work.
$i is faster because it only requires 3 instructions (opcodes), while $i requires 4 instructions.
Postincrement actually creates a temporary variable that is subsequently incremented.
The prefix increment increases directly on the original value.
This is a type of optimization, just like Zend's PHP optimizer does.
Keep in mind that this optimization is a good idea because not all instruction optimizers will do the same optimization.
4.9 Don’t copy variables casually
Sometimes in order to make the PHP code cleaner, some PHP newbies (including me) will copy the predefined variables into a variable with a shorter name. .
In fact, the result of this is to double the memory consumption, which will only make the program slower.
Just imagine, in the following example, if the user maliciously inserts 512KB of text, 1MB of memory will be consumed!
// 不好的实践 $description = $_POST['description']; echo $description; // 好的实践 echo $_POST['description'];
4.10 循环内部不要声明变量
尤其是大变量,这好像不只是PHP里面要注意的问题吧?
4.11 一定要对变量进行初始化
这里的“初始化”指的是“声明”。
当需要没有初始化的变量,PHP解释器会自动创建一个变量,但依靠这个特性来编程并不是一个好主意。
这会造成程序的粗糙,或者使代码变得另人迷惑。
因为你需要探寻这个变量是从哪里开始被创建的。
另外,对一个没有初始化的变量进行递增操作要比初始化过的来得慢。
所以对变量进行初始化会是个不错的主意。
5 数组
5.1 用字符串而不是数组作为参数
如果一个函数既能接受数组,又能接受简单字符做为参数,那么尽量用字符作为参数。
例如,字符替换函数,参数列表并不是太长,就可以考虑额外写一段替换代码。
使得每次传递参数都是一个字符,而不是接受数组做为查找和替换参数。
5.2 数组元素加引号
$row['id']比$row[id]速度快7倍。
如果不带引号,例如$a[name],那么PHP会首先检查有没有define定义的name常量
如果有,就用这个常量值作为数组键值。如果没有,再查找键值为字符串'name'的数组元素。
多了一个查找判断的过程,所以建议养成数组键名加引号的习惯。
正如上面字符串部分所述,用'又比用"速度更快。
5.3 多维数组操作
多维数组尽量不要循环嵌套赋值。
5.4 循环用foreach
尽量用foreach代替while和for循环,效率更高。
6 架构
6.1 压缩输出
在php.ini中开启gzip压缩:
zlib.output_compression = On
zlib.output_compression_level = (level)
level可能是1-9之间的数字,你可以设置不同的数字。
几乎所有的浏览器都支持Gzip的压缩方式,gzip可以降低80%的输出.
付出的代价是,大概增加了10%的cpu计算量。
但是还是会赚到了,因为带宽减少了,页面加载会变得很快。
如果你使用apache,也可以激活mod_gzip模块。
6.2 静态化页面
Apache/Nginx解析一个PHP脚本的时间,要比解析一个静态HTML页面慢2至10倍。
所以尽量使页面静态化,或使用静态HTML页面。
6.3 将PHP升级到最新版
提高性能的最简单的方式是不断升级、更新PHP版本。
6.4 利用PHP的扩展
一直以来,大家都在抱怨PHP内容太过繁杂。
最近几年来,开发人员作出了相应的努力,移除了项目中的一些冗余特征。
即便如此,可用库以及其它扩展的数量还是很可观。
甚至一些开发人员开始考虑实施自己的扩展方案。
6.5 PHP缓存
一般情况下,PHP脚本被PHP引擎编译后执行,会被转换成机器语言,也称为操作码。
如果PHP脚本反复编译得到相同的结果,为什么不完全跳过编译过程呢?
PHP加速器缓存了编译后的机器码,允许代码根据要求立即执行,而不经过繁琐的编译过程。
对PHP开发人员而言,目前提供了两种可用的缓存方案。
一种是APC(Alternative PHP Cache,可选PHP缓存),它是一个可以通过PEAR安装的开源加速器。
另一种流行的方案是OPCode,也就是操作码缓存技术。
6.6 使用NoSQL缓存
Memchached或者Redis都可以。
这些是高性能的分布式内存对象缓存系统,能提高动态网络应用程序性能,减轻数据库的负担。
这对运算码 (OPcode)的缓存也很有用,使得脚本不必为每个请求重新编译。
The above is the detailed content of Some suggestions for improving PHP efficiency and optimization. For more information, please follow other related articles on the PHP Chinese website!