Home > Article > Backend Development > PHP performance optimization encyclopedia (php.ini), performance optimization php.ini_PHP tutorial
Chapter 1 Optimization for excessive system calls
My optimization this time is aimed at the problem of too many syscall calls, so I use strace to track apache for analysis.
1. apache2ctl -X &
Use the -X (debug) parameter to start the httpd process. At this time, only 1 httpd process is started
2. ps -ef | grep httpd
Find the pid that requires strace
3. strace -p $PID -o /tmp/strace.log
Send an http request to httpd and you can see the strace information.
1. Include_path problem
You can generally see a lot of this kind of information:
stat64("/error/dir/test.php", 0xbfab4b9c) = -1 ENOENT (No such file or directory)
Solution:
1. Set include_path in the application php, remove relative paths such as '.', and put the directory containing more files in front. Ensure that it can be found quickly when traversing include_path.
2. Use absolute paths for include, require, include_once, require_once
3. Use PHP’s automatic loading mechanism
2. Apache rewrite configuration
Copy code The code is as follows:
RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
RewriteRule .* %{DOCUMENT_ROOT}%/index.php
#RewriteRule .* /index.php
The last commented out rewrite configuration here is not good because it will cause one more syscall for each request
stat64("/index.php", 0xbfab4b9c) = -1 ENOENT (No such file or directory)
3. Apache log problem
When we were testing a problem, we found that if the custom log records access time and other information, there will be a lot
stat64("/etc/localtime", {st_mode=S_IFREG|0644, st_size=165, ...}) = 0
If a large number of logs are recorded, the performance will be degraded very seriously. For simple applications, if complex logs are recorded, the performance will be degraded by 30 times.
Solution:
Set up http layer proxies on multiple apache front ends, such as haproxy and nginx. Keep logs in these places. The access layer load is generally not high, so the proxy can do some logging work. In this configuration, apache's logs can be turned off.
4. Realpath() problem
You can take a look at this article: http://bugs.php.net/bug.php?id=43864
After lstat64 is called too many times, the host CPU and IO will be relatively high.
The reason is that php5.2.x does not implement realpath() well enough, resulting in lstat64() being called level by level for the directory hierarchy.
In order to solve this problem, it uses realpath_cache to store the realpath of a certain file. Only the realpath of the leaf nodes is stored here, but the content on the path is not stored, so when doing the "/a/b/c/d/e/f/g/a.php" realpath check, lstat64 is called step by step. When checking "/a/b/c /d/e/f/g/b.php", you also need to check "/a/b/c/d/e/f/g/" one by one. level check. So some optimization suggestions are to "reduce the directory level, or even put it in the "/" root directory. Of course, I don't recommend this. Starting from 5.3.0, PHP has implemented realpath() efficiently, using realpath. The intermediate path is also cached. Taking the above situation as an example, when checking "/a/b/c/d/e/f/g/b.php", only "b.php" will be checked. .So, upgrading to php5.3.0 or above can solve this problem well
Solution:
1. Use include_once and require_once as little as possible
Because these two functions will perform realpath checks to prevent repeated loading due to symbolic links. Not using them can reduce realpath calls.
2. Properly set the realpath_cache_size and realpath_cache_ttl parameters in php.ini
Since realpath_cache is used, there must be a size limit. For projects that use a lot of files, such as Zend Framework, the default realpath_cache_size=16k may be too small. You need to increase this setting. It is recommended to set it to 256K or more. In addition, the default realpath_cache_ttl=120 is expired in 2 minutes, so it must be set to 3600 (1 hour).
What needs to be noted here is that this realpath_cache is exclusive to every apache process, so it consumes a lot of memory and cannot be set too large.
3. Upgrade to php5.3.x
There is nothing much to say. If the application has been tested in detail and there are no problems, then it is recommended to upgrade to a higher version.
5. Use of APC
apc can cache the opcode code of php, which can generally improve performance by 30%. But the default apc.stat=1, so that each request will access the php file that needs to be used, see if this file has been updated, and decide whether to recompile the php file. This is very performance consuming and is recommended to be turned off.
Solution:
1. Set apc.stat=0, so you don’t have to access the required php files every time you request it.
What needs to be noted is: every time you publish a version that changes the php file, you must call apc_clear() to clear the apc cache, otherwise your code will never take effect.
6. Smarty tuning
For websites with good modularity and many applications, if the smarty template system is used, smarty needs to be tuned at this time, otherwise the smarty part will cost a lot of money. According to previous experience, smarty can account for about 10% of the expenses.
Under the default configuration, smarty detects whether each template file has been updated and decides whether to recompile the template file. If there are many template files, there will be many more stat system calls, and with context switch, the overhead will be considerable.
Solution:
1. $smarty->compile_check = false;
Remove each detection, but after this, you must delete the compiled templates in the compile_dir directory every time you release a version, otherwise your template files will never take effect.
2. If possible, use the cache function.
Conclusion
After the above tuning, the conclusion is as follows:
1. Upgrade to php5.3.1 to enable the above optimization, which is more than 10% better than 5.2.3
2. Under optimized configuration, a search application developed using Zend Framework can reach 210 requests per second/rps
3. Under optimized configuration, a search application developed using doophp framework can reach 450 requests per second/rps
Chapter 2 Using APC Cache
Execution process of php program
—》Client (browser) requests Get hello.php
—-》The cgi server (such as apache) receives the request and looks for the php handler (such as mod_php) according to the configuration
—-》Apache loads the php handler, and the php handler reads php.ini to initialize the php interpretation environment
—-》mod_php locates hell.php and loads it into memory
—-》mod_php compiles the source code into an opcode tree
—-》mod_php executes opcode tree
—-》Generate results to the browser
During this process, there are several points that need to be noted:
1. For many code files, especially those containing many include files (include or require). They take more time to parse and generate intermediate code.
2. Even if the PHP code file has not changed, the execution process will be executed strictly in accordance with the process. In other words, no matter whether your application program changes or not, you need to recompile and generate opcode every time you call it. (In fact, this is the reason why the compilation cache exists)
3. This process not only occurs in the main code file, but also is executed for every include and require. (This can continue to be optimized)
What areas can be optimized?
1. Make mod_php fast-cgi to avoid loading this module every time. This module also needs to initialize the PHP interpretation environment every time.
2. Cache the opcode code of the php file, so as to avoid compiling it every time.
APC can be used to achieve point 2. The compile cache removes the parsing process during PHP execution, so it is very effective for applications containing a large amount of PHP code. Under normal circumstances, the speed can be increased by more than 2-3 times. For projects that contain a large number of include files, compilation caching can better demonstrate its advantages.
Note: include will not be cached by the compilation cache. For example, there are two files: main.php and tobeInclude.php. Main.php has the statement include tobeInclude.php'. It is assumed that the suffix of the intermediate code is .op (this is not the case). Then after adding the cache main.php=>main.op, tobeInclude.php=>tobeInclude.op. But when PHP executes main.php, she still needs to parse the include command in main.op and call the content of tobeInclude.op. The specific process is as follows.
…=>Execute main.op=>Execute tobeInclude.op=>…
Rather than simply executing main.op
So it is said that "too many include files will reduce program performance."
The specific configuration of APC.
Alternative PHP Cache (APC) is a free and public optimized code cache for PHP. It is used to provide a free, open and robust framework for caching and optimizing PHP intermediate code.
The official website of APC is http://pecl.php.net/package/apc
1. Installation
Install as PHP extension
phpize
./configure --enable-apc --enable-apc-mmap
make
make install
Generate .so, copy .so to the directory where PHP references modules, and modify the permissions to 755
2. Configuration
apc.enabled boolean
apc.optimization optimization
Options can be changed in script
Detailed explanation of APC PHP.ini configuration options
[APC]
; Alternative PHP Cache for caching and optimizing PHP intermediate code
apc.cache_by_default = On
;SYS
; Whether to enable buffering by default for all files.
; If set to Off and used with the apc.filters directive starting with a plus sign, files will only be cached if they match a filter.
apc.enable_cli = Off
;SYS
; Whether to enable APC functionality for CLI builds, turn this directive on for testing and debugging purposes only.
apc.enabled = On
; Whether to enable APC, if APC is statically compiled into PHP and want to disable it, this is the only way.
apc.file_update_protection = 2
;SYS
; When you modify files on a running server, you should perform atomic operations.
; That is, first write to a temporary file, and then rename (mv) the file to the final name.
; Text editors and programs such as cp and tar do not operate in this way, resulting in the possibility of buffering incomplete files.
; The default value 2 means that when accessing a file, if the modification time is found to be less than 2 seconds from the access time, no buffering will be performed.
; The unlucky visitor may get corrupted content, but the bad effect is not amplified by caching.
; If you can ensure that all update operations are atomic, you can turn off this feature with 0.
; If your system updates slowly due to heavy IO operations, you may need to increase this value.
apc.filters =
;SYS
; A comma-separated list of POSIX extended regular expressions.
; If the source file name matches any of the patterns, the file is not cached.
; Note that the file name used to match is the file name passed to include/require, not the absolute path.
; If the first character of the regular expression is " " it means that any files matching the expression will be cached,
; If the first character is "-" then any matches will not be cached. "-" is the default value and can be omitted.
apc.ttl = 0
;SYS
; The number of seconds a cache entry is allowed to stay in the buffer. 0 means never times out. The recommended value is 7200~36000.
; Setting to 0 means that the buffer may fill up with old cache entries, preventing new entries from being cached.
apc.user_ttl = 0
;SYS
; Similar to apc.ttl, but for each user, the recommended value is 7200~36000.
; Setting to 0 means that the buffer may fill up with old cache entries, preventing new entries from being cached.
apc.gc_ttl = 3600
;SYS
; The number of seconds a cache entry can exist in the garbage collection table.
; This value provides a safety measure even if a server process crashes while executing a cached source file,
; and the source file has been modified, the memory allocated for the old version will not be reclaimed until this TTL value is reached.
; Set to zero to disable this feature.
apc.include_once_override = Off
;SYS
; Please keep it Off, otherwise it may cause unexpected results.
apc.max_file_size = 1M
;SYS
; Prevent files larger than this size from being cached.
apc.mmap_file_mask =
;SYS
; If MMAP support was compiled for APC using --enable-mmap (enabled by default),
; The value here is the mktemp-style file mask passed to the mmap module (the recommended value is "/tmp/apc.XXXXXX").
; This mask is used to determine whether the memory mapped area should be file-backed or shared memory backed.
; For direct file-backed memory mapping, set it to "/tmp/apc.XXXXXX" (exactly 6 X's).
; To use POSIX-style shm_open/mmap, it needs to be set to "/apc.shm.XXXXXX".
; You can also set to "/dev/zero" to use the kernel's "/dev/zero" interface for anonymously mapped memory.
; Not defining this directive forces the use of anonymous mapping.
apc.num_files_hint = 1000
;SYS
; The approximate number of different source files that may be included or requested on the web server (recommended value is 1024~4096).
; If you are unsure, set to 0 ; This setting is mainly useful for sites with thousands of source files.
apc.optimization = 0
; Optimization level (recommended value is 0).
; A positive integer value enables the optimizer, with higher values using more aggressive optimizations.
; Higher values may have very limited speed improvements, but are currently experimental.
apc.report_autofilter = Off
;SYS
; Whether to record all scripts that are automatically not cached due to early/late binding reasons.
apc.shm_segments = 1
;SYS
; The number of shared memory blocks allocated for the compiler buffer (recommended value is 1).
; If APC has exhausted shared memory and the apc.shm_size directive has been set to the maximum allowed by the system,
; You can try increasing this value.
apc.shm_size = 30
;SYS
; The size of each shared memory block (in MB, the recommended value is 128~256).
; Some systems (including most BSD variants) have a very small default shared memory block size.
apc.slam_defense = 0
;SYS (It is against the use of this command, it is recommended to use the apc.write_lock command)
; On a very busy server, whether starting a service or modifying a file,
; can cause a race condition due to multiple processes trying to cache a file at the same time.
; This directive is used to set the percentage at which the process skips the caching step when processing uncached files.
; For example, setting it to 75 means that there is a 75% probability of not caching when an uncached file is encountered, thereby reducing the chance of collision.
; Encouraged to be set to 0 to disable this feature.
apc.stat = On
;SYS
; Whether to enable script update checking.
; Be very careful when changing this directive value.
; The default value On means that APC checks whether the script has been updated every time it is requested,
; Automatically recompile and cache the compiled content if updated. However, doing so has a negative impact on performance.
; If set to Off, no checking is performed, thus greatly improving performance.
; But in order for the updated content to take effect, you must restart the web server.
; This directive is also valid for include/require files. But it should be noted that
; If you use relative paths, APC must check to locate the file on every include/require.
; Using absolute paths can skip the check, so you are encouraged to use absolute paths for include/require operations.
apc.user_entries_hint = 100
;SYS
; Similar to the num_files_hint directive, but for each different user.
; Set to 0 if you are not sure.
apc.write_lock = On
;SYS
; Whether to enable write lock.
; On a very busy server, whether starting a service or modifying a file,
; can cause a race condition due to multiple processes trying to cache a file at the same time.
; Enable this directive to avoid race conditions.
apc.rfc1867 = Off
;SYS
; After turning on this directive, APC will automatically create a user cache entry for upload_ (that is, the APC_UPLOAD_PROGRESS field value) for each uploaded file that contains the APC_UPLOAD_PROGRESS field just before the file field.
3. php function
apc_cache_info - Retrieves cached information (and meta-data) from APC's data store
apc_clear_cache - Clears the APC cache
apc_define_constants - Defines a set of constants for later retrieval and mass-definition
apc_delete - Removes a stored variable from the cache
apc_fetch - Fetch a stored variable from the cache
apc_load_constants - Loads a set of constants from the cache
apc_sma_info - Retrieves APC's Shared Memory Allocation information
apc_store - Cache a variable in the data store
4. Note:
Apc and apache processes share memory, so values can be stored in apc only when the apache process is executed. Ordinary php processes cannot access apc shared memory.
Chapter 3 Coding Tips to Improve PHP Performance
0. Use single quotes instead of double quotes to include strings, which will be faster. Because PHP will search for variables in strings surrounded by double quotes, single quotes will not. Note: only echo can do this, it is a "function" that can take multiple strings as parameters (Annotation: PHP Manual It is said that echo is a language structure, not a real function, so the function is enclosed in double quotes).
1. If you can define a class method as static, try to define it as static, and its speed will increase by nearly 4 times.
2. The speed of $row['id'] is 7 times that of $row[id].
3. Echo is faster than print, and uses multiple parameters of echo (annotation: refers to using commas instead of periods) instead of string concatenation, such as echo $str1, $str2.
4. Determine the maximum number of loops before executing the for loop. Do not calculate the maximum value every loop. It is best to use foreach instead.
5. Unregister unused variables, especially large arrays, to free up memory.
6. Try to avoid using __get, __set, __autoload.
7. require_once() is expensive.
8. Try to use absolute paths when including files, because it avoids the speed of PHP searching for files in include_path, and the time required to parse the operating system path will be less.
9. If you want to know the time when the script starts executing (annotation: the server receives the client request), it is better to use $_SERVER['REQUEST_TIME'] than time().
10. Functions replace regular expressions to complete the same function.
11. The str_replace function is faster than the preg_replace function, but the strtr function is four times more efficient than the str_replace function.
12. If a string replacement function can accept arrays or characters as parameters, and the parameter length is not too long, then you can consider writing an additional piece of replacement code so that each parameter passed is a character, instead of just writing one line of code to accept an array. As parameters for queries and replaces.
13. It is better to use a selective branch statement (translation annotation: switch case) than to use multiple if, else if statements.
14. Using @ to block error messages is very inefficient, extremely inefficient.
15. Open apache's mod_deflate module to increase the browsing speed of web pages.
16. The database connection should be closed when finished using it, and do not use long connections.
17. Error messages are expensive.
18. Incrementing local variables in methods is the fastest. Almost as fast as calling local variables in a function.
19. Incrementing a global variable is 2 times slower than incrementing a local variable.
20. Incrementing an object property (such as: $this->prop) is 3 times slower than incrementing a local variable.
21. Incrementing an undefined local variable is 9 to 10 times slower than incrementing a predefined local variable.
22. Just defining a local variable without calling it in the function will also slow down the speed (to the same extent as incrementing a local variable). PHP will probably check to see if a global variable exists.
23. Method calls appear to be independent of the number of methods defined in the class, as I added 10 methods (both before and after testing the method) and there was no change in performance.
24. Methods in derived classes run faster than the same methods defined in base classes.
25. Calling an empty function with one parameter takes the same time as performing 7 to 8 local variable increment operations. A similar method call takes close to 15 local variable increments.
26. Apache parses a PHP script 2 to 10 times slower than parsing a static HTML page. Try to use more static HTML pages and less scripts.
27. Unless the script can be cached, it will be recompiled every time it is called. Introducing a PHP caching mechanism can usually improve performance by 25% to 100% to eliminate compilation overhead.
28. Try to cache as much as possible, you can use memcached. Memcached is a high-performance memory object caching system that can be used to accelerate dynamic web applications and reduce database load. Caching of OP codes is useful so that scripts do not have to be recompiled for each request.
29. When operating a string and need to check whether its length meets certain requirements, you will naturally 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 (Annotation: refers to the lowercase function name, PHP does not distinguish between uppercase and lowercase function names), hash search, Will be executed together with the called function. In some cases, you can use the isset() trick to speed up the execution of your code.
(Example below)
if (strlen($foo) < 5) { echo "Foo is too short"$$ }
(Compare with the tips below)
if (!isset($foo{5})) { echo "Foo is too short"$$ }
Calling isset() happens to be faster than strlen() because, unlike the latter, isset(), as a language construct, means that its execution does not require function lookups and lowercase letters. That is, you actually don't spend much overhead in the top-level code checking the string length.
34. 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. Post-increment actually creates a temporary variable that is subsequently incremented. Prefix increment increases directly on the original value. This is a form of optimization, as done by Zend's PHP optimizer. It's a good idea to keep this optimization in mind because not all command optimizers do the same optimizations, and there are a large number of Internet Service Providers (ISPs) and servers that don't have command optimizers equipped.
35. Not everything must be object-oriented (OOP), object-oriented is often very expensive, and each method and object call consumes a lot of memory.
36. It is not necessary to use classes to implement all data structures. Arrays are also useful.
37. Don’t subdivide the methods too much. Think carefully about which code you really intend to reuse?
38. You can always break code into methods when you need to.
39. Try to use as many PHP built-in functions as possible.
40. If there are a large number of time-consuming functions in the code, you can consider implementing them as C extensions.
41. Profile your code. The checker will tell you which parts of the code take how much time. The Xdebug debugger includes inspection routines that evaluate the overall integrity of your code and reveal bottlenecks in your code.
42. mod_zip can be used as an Apache module to instantly compress your data and reduce data transmission volume by 80%.
43. When file_get_contents can be used instead of file, fopen, feof, fgets and other series of methods, try to use file_get_contents because it is much more efficient! But please pay attention to the PHP version problem of file_get_contents when opening a URL file;
44. Conduct file operations as little as possible, although PHP’s file operation efficiency is not low;
45. Optimize the Select SQL statement and perform as few Insert and Update operations as possible;
46. Use PHP internal functions as much as possible (but in order to find a function that does not exist in PHP, I wasted time that could have been written a custom function, a matter of experience!);
47. Don’t ** variables inside the loop, especially large variables: objects (this seems to be not just a problem in PHP, right?);
48. Try not to nest assignments in loops for multi-dimensional arrays;
49. Do not use regular expressions when you can use PHP’s internal string manipulation functions;
50. foreach is more efficient, try to use foreach instead of while and for loop;
51. Use single quotes instead of double quotes to quote strings;
52. "Replace i=i 1 with i =1. It conforms to the c/c habit and is more efficient";
53. Global variables should be unset()ed after use;