Contacts

Acceleration of PHP programs. PHP optimization is the hallmark of professional eAccelerator code: faster PHP code reloads

When developing large projects, the question of optimizing the project code gradually arises: how justified is the memory consumption, how can you increase the speed of execution of the written php code. At first, many do not think about the correctness and efficiency of the written code, they write according to the principle: it works - and that's fine. Even though the PHP interpreter executes PHP code quite quickly, and there are many bottlenecks that slow down the speed of code execution that are outside of PHP, PHP code optimization is also important, and code optimization should be applied already at the beginning of the coding process. .

Most PHP scripts do simple things. The script's default behavior is to load a small amount of information from the user, get some information from a database or file, output the appropriate HTML, and send the output to the client. Here, first of all, you need to understand what exactly should be the result of optimization: speed, ease of scaling, reduction in the amount of server resources used, reduction in data transfer time, or all together. In the latter case, it is necessary not only to find all critical sections, but also to balance their optimization.

Let me give you the simplest example, let's say that on a server with 100 MB of free RAM, there are two scripts, the result of which is the same. The first script is optimized for maximum performance, requires 10 MB of memory and receives data from the file by reading it completely, the second - for minimal memory consumption, requires 5 MB of memory and receives data from the same file in parts. As a result of one request, the first script will be executed faster than the second, but if there are more than ten requests at the same time, it is the speed of the second script that will become faster. Why is this happening? In the first script, the bottleneck is the use of memory resources, in the second - the features of the I / O system. After the first script consumes all available RAM, the system will switch to using virtual memory, while the same I / O system will become an additional bottleneck of this scheme.

Of course, this example is greatly simplified, and there are other bottlenecks besides RAM, but the main idea is this: optimization for one case can become a critical place in another. In the example, as a result of optimization for a slight increase in speed at low loads, the script execution speed significantly decreased at higher loads. Therefore, in order to get a higher return, it is important to spend your energy on optimizing areas that really deserve attention.

I will not consider here the optimization of the operating system, the optimization of server settings, etc., because. most webmasters use hosting and, accordingly, will not be able to set everything up on their own. Only php code optimization will be considered here. It should be noted that in each case, some types of optimization will be useful, others will be a waste of time and effort. Often the usefulness of a code improvement will be negligible. Perhaps over time, internal changes to PHP will render successful optimizations useless or even harmful.

The following are the main performance improvements for PHP 5:

Steps to optimize RAM consumption:

  1. Analysis of the results of your functions. Before writing a function, check if there is a standard equivalent.
  2. Freeing memory in case of end of using large arrays or objects only in the global scope (memory will be freed automatically in the local scope). Please note that the function unset() removes the variable from the scope and, only if there are no other references to the object, releases the memory occupied by the object. Assigning a value to a variable null always destroys the object and frees the memory occupied by the object, regardless of whether there are still references to this object. In this case, the variable will not be removed from the scope, i.e. in fact, the variable will contain an undefined (zero) value and, accordingly, will occupy memory for the contents of this variable (about 72 bytes).
  3. Analysis of the justification for using OOP (object-oriented programming). Before writing object-oriented code, ask yourself two questions: “is an object-oriented approach necessary here?” and “can I write object-oriented code?”. For example, defining a static function within a class increases the amount of memory required just to contain that function by 10-18%. Using an array as a structure rather than a class also saves memory. It may be more beneficial to just put the functions in a separate file, rather than implement them as class methods.
  4. Analysis of the possibility of implementing a static version of a method in a class. If the method does not use the parameter $this, then it must be declared using the keyword static.

Actions to increase the speed of code execution:

  1. Analysis of the optimization of SQL queries. In most projects, it is the optimization of SQL queries that gives the greatest performance increase.
  2. The use of output buffering, various caching modules, allows you to increase performance by 25% -100%.
  3. Using shorter short names for variables, functions, constants, and classes can improve performance by up to 20%. At the same time, don't forget about future code support, a self-explanatory function name is much more convenient when modifying the code.
  4. Checking for the existence of a variable (function isset()) before contacting it. Suppressing the error that occurs when accessing a non-existent variable by using @ greatly reduces performance.
  5. Using "single quotes" allows you to interpret the code faster, because in the case of "double quotes", variables are searched inside the string
  6. Analysis of the possibility of removing "extra" functions from the cycle. For example, replacing the function count() to a variable calculated before the start of the loop and containing the result of this function, in the expression for($i=0; $i will improve the performance of this cycle. Otherwise, the function count() will be called and executed on each iteration of the loop.
  7. Operator usage case instead of multiple use of the construct if...else.
  8. Using explicit access to array fields. View reversal $array["id"] runs 7 times faster than inverting $array. In addition, it protects against errors during further maintenance of the script, because. one day there may be a constant named id.
  9. Using an additional variable containing a reference to the final array when processing multidimensional arrays in a loop. To speed up the cycle for($i = 0; $i< 5; $i++) $a["b"]["c"][$i] = func($i); , before the start of the loop it is possible to write the following instruction $item =p$a["b"]["c"] and rewrite the loop like this: for($i = 0; $i< 5; $i++) $ref[$i] = $i; .
  10. Using the Apache modules mod_gzip and mod_deflate allows you to reduce traffic, thereby increasing the speed of loading pages.

The following code optimization steps improve performance only when reused:

  1. Usage ++$i instead of $i++ in cycles gives a performance increase of 6%.
  2. Using "double quotes" to concatenate (glue) variables. View instruction $s="$s1$s2$s3" interpreted faster than $s=$s1.$s2.$s3. This statement is true only for three or more variables.
  3. Using Full Paths in Instructions include And require will allow you to spend less time searching for a real path by the system.
  4. Closing open database connections when they are no longer needed. At the same time, you should not connect to the same database multiple times.
  5. Replacement feasibility analysis include() And include_once() on require() And require_once() respectively.
  6. Using HTML inserts in the code, instead of outputting a significant amount of statico lines (not containing the results of the code). In general, the speed of issuing a static page (HTML) is several times faster than issuing a page written in PHP. But here you should not get carried away, because. input to the interpreter in PHP processing mode and output from it also load the server.
  7. Analysis of the possibility of replacing functions preg_replace And str_replace in some cases. Function str_replace works faster than preg_replace, and at the same time the function strtr faster function str_replace. Also, using string functions strncasecmp, strpbrk And stripes more optimal than using regular expressions. However, instead of nesting these functions, you should use regular expression functions.
  8. Using explicit variable initialization. For example, incrementing an uninitialized variable is 9-10 times slower than a pre-initialized one. Also, there are fewer errors when explicitly initializing variables.
  9. As a conclusion, I would like to note that the use of the construction echo, instead of a function print, does not give a noticeable increase in performance.
  • To determine the start time of script execution, instead of functions that return the current time, it is preferable to use $_SERVER["REQUEST_TIME"].
  • Use a profiler to identify critical sections of code.

Before optimizing the performance of the code, I strongly recommend checking the optimization of SQL queries to the database, as well as optimizing http queries, reducing the size of js and css, thinking about template caching, and only after that start checking the code for performance.

A good programming style is about optimizing while writing code, not patching holes later.

There are a number of rules that should be followed in order to increase the speed of PHP applications. The rules are simple and will not require major changes to existing applications.

fastcgi

FastCGI is one of the options for connecting PHP to a Web server. Best used in conjunction with Nginx. PHP-fpm (Fastcgi container for PHP) and Nginx work together by default and are very easy to set up.

OpCache


How is a PHP script usually executed? PHP opens the code file, compiles it, then executes it. Since there can be many files, the process of opening, reading and compiling them can take a lot of resources. If the files do not change, then constant compilation may not be done. It is better to do it once and cache the result.

This is exactly what the opCache module does. The result of the first compilation will be stored in the cache, which PHP will work with. Thus, it will speed up the execution due to the absence of a heavy compilation process. When the files change, the module itself will reset the cache and ensure recompilation. In short, this module makes a very useful resource saver. And that's without having to set it up.

As of PHP5.5+, this module is shipped as a standard build. In previous versions, you need to install the module yourself. You can check for availability like this: php -i | grep opcache

# An empty output will mean that the module is not present

If the version is too early, it's better to use APC: apt-cache search php-apc

# This is an alternative to opCache, but does the same

caching

Often the code is just slow. For example:

  • accessing external APIs
  • heavy selections from databases
  • processing large files
session.save_handler = memcache session.save_path = "tcp:// localhost:11211"

# localhost:11211 is the default Memcache host and port

In addition, such a storage scheme will allow scaling to multiple servers.

Code optimization

OOP

Remember! OOP is always slow. Objects need to be created, stored somewhere and destroyed. Don't use objects if you don't need them. For example, here:

set_title($_GET["title"]); $post->set_description($_GET["description"]); $post->save();

# $posts = list of Post objects received somehow foreach ($posts as $post) ( echo $post->title . "
"; }

# Use the list of objects only to display the property

In these examples, using OOP doesn't make much sense. But it consumes resources. Try to use arrays when you don't need objects:

$_GET["title"], "description" => $_GET["description"]]);

# Avoided creating an object, the function just saves the data from the array to the base

"; }

# Much better - make a simple selection and output the desired data from the array

little things

When working with files, use absolute paths. Then unnecessary file search operations will not occur:

include "/var/www/file.php"; file_get_contents("/var/www/dir/data.txt");

Class constants work more efficiently than define:

class posts ( const PER_PAGE = 10; ... )

Don't use functions in the for clause, because they will be repeated on each iteration of the loop:

$max = mysql::get_col("SELECT count(*) FROM posts"); for ($i = 0; $i< $max; $i++) { ... }

Always specify strings as array keys with quotes:

$post["title"] = "First Post";

Use the built-in string functions instead of regular expressions if possible.

strpos($post["title"], "good");

Use strings with single quotes:

$post["title"] = "There is no additional variable processing in this case"

PHP cron scripts

When PHP is used to develop a script that will be executed by cron, the use of global variables should be avoided. For example:

(.+?)<\/title/", $rss, $matches); }

(.+?)<\/title/", $rss); if ($has_something) $updates= time(); $rss = file_get_contents("http://othersource.com/rss"); $has_something = preg_match("/title>(.+?)<\/title/", $rss); if ($has_something) $updates= time(); )

The $updates variable will now grow to its maximum limit. When the memory limit is reached, the script will be stopped. Keeping track of all the variables is quite difficult, so it's better to use functions. All variables created inside the function will be deleted after it ends:

process(); function process() ( $rss = file_get_contents("http://somesite.com/rss"); $has_something = preg_match("/title>(.+?)<\/title/", $rss); if ($has_something) $updates = time(); $rss = file_get_contents("http://othersource.com/rss"); $has_something = preg_match("/title>(.+?)<\/title/", $rss); if ($has_something) $updates = time(); }

The most important

  • Be sure to use opCache for PHP. This for free saves resources.
  • Use FastCGI (Nginx + PHP-fpm is best).
  • Functions in cron tasks will help to avoid memory leaks.
  • Caching slow sections of code is often the easiest solution to speed up work.
  • Remember about

The performance of PHP solutions is a frequent topic of various disputes and discussions. We will not participate in them now. After all, be that as it may, everything always depends on the specific task. For example, I know of a reliable case when a certain program code was rewritten in Assembler for a year and a half. It was originally written in C. When the work was completed, hundreds of working days of a large group of developers were left behind, and a version of the software written entirely in Assembler was in hand. What a surprise the team was when, as a result, their creation in Assembler worked much slower than their earlier creation in C!

Code optimization is a multifaceted task. There are many factors to consider. It should be understood that in some cases it can be neglected altogether: after all, it is often easier to buy additional high-performance hardware than to pay for the additional work of a team of high-class developers. Automation, industrialization, my friends! Robots are replacing people. But once upon a time there were such professions as, for example, the profession of a lamplighter or an elevator operator, no, not the one who now repairs and maintains elevators. The one who used to be the navigator of the elevator and took passengers where they asked. Now it already seems ridiculous. And in a certain number of years, aircraft pilots will cause laughter. Those will fly on fully automated control systems, etc.

Either way, there is no point in optimizing very simple or rarely used pieces of software. At least until everything else is in order. And what exactly should you pay attention to in the first place? Now we will talk about this.

Let's take PHP as an example. In fact, no matter what they say about it, PHP is no worse than Perl or ASP.NET, I would even say the opposite - PHP has much more advantages. Why does he get it the most? Very simple - because it is the most popular! After all, Windows is also scolded by everyone, it has the most viruses under it, it has the most “holes” found. But its popularity is worth it ... Hmm, more than 98% of users work under Windows OS. All other operating systems combined account for no more than 2% of users. No wonder Windows gets so much attention. I am sure that if any other OS were as popular (and as complex, functional and accessible), it would be found no fewer holes. Well, okay, this is a conversation for a separate topic.

Returning to PHP, among other things, this is perhaps the most simple programming language widely used for the web. Its simplicity and accessibility determine the emerging army of beginners who are trying to do at least something in it. Their incompetence often leads to negative discussions about PHP. The same ASP.NET is not so accessible. As a result, its main “carriers” are quite literate people. With all the ensuing consequences. But the availability of PHP in no way negates its merits in the hands of professionals.

After all, what is the most popular social network, and the second most visited web resource in the world, facebook written in? And its analogue is vkontakte? Of course, in PHP!

Understand the scope. If you need to carry out serious calculations, especially those related to multimedia, with big data and high loads, for example, online video processing, of course, it is better to write the corresponding code in the same C and already use it under PHP as a compiled module. PHP is more of a universal template engine than a programming language as we understand it. PHP has a completely different task.

In this regard, in optimizing the performance of PHP code, the approaches are different: here it is more important to optimize the algorithm itself, the problem solving model, than the specific code. Although there are exceptions.

7 principles, or 7 positions of PHP code optimization.

1) Love for ready-made libraries.

Various ready-made libraries are definitely useful and convenient things. But we should not forget that free cheese is only in a mousetrap. For everything, one way or another, but you have to pay.

Developing software to implement the ideas of a certain site will always (subject to comparable levels of performers, of course) in terms of performance be much more profitable than using a ready-made, universal CMS (Content Management System - content management system, site "engine"). Poor performance is the cost of CMS versatility. This is the same as going to the market on a private bus, or even on an airplane, but not in your own car. It's the same with ready-made libraries.

But why did I put libraries in the first place? Because if they are used, they immediately eat up the lion's share of productivity. See for yourself: Connecting alone Smarty And DbSimple immediately "eats" about 0.025 sec. time and almost 3/4 MB of RAM. And this is on a good server with a low overall load. Add some more here phpMailer, and we have 0.03 sec. time spent and 1 MB of memory gobbled up simply from scratch. We have not done anything yet, just connected the modules, this is even without their initialization! I have one self-written project, like a social network, so on average it takes significantly less resources to completely create a page. Another example is a news site engine that I developed: posts, comments, etc. By and large, nothing super complicated, but the speed is decent - on average, less than 0.001 sec. for page generation and up to 0.15 MB of memory. Projects are built on a bunch of PHP + MySQL. By the way, in this way, the second of them calmly holds more than 400 thousand. hits per day, with bursts of up to 1600 hits per minute in spades and almost 500 hosts online. On VPS for $30/month. And connect those three libraries to it, then you can’t do without a dedicated server, and not the weakest configuration. But it often comes to the use of a dozen ready-made libraries.

On the other hand, of course, if you are developing a small site - for a company, or a personal page, it makes no sense to take care of optimization, and thus refuse to use ready-made libraries. Time is more valuable. If your site traffic is not more than 1000 visitors per day, you should not waste time on a perfect and fast code. Use ready-made libraries. You will have enough resources of any good shared hosting. If your traffic reaches 2-3 thousand visitors per day, it already makes sense to think about optimizing the code. But still, you should think carefully about whether you should abandon ready-made libraries at this stage and kill time to rework the code (or time and money for the programmer who will do it). It is often easier to just buy additional resources, or switch to VPS, paying $10-50 per month.

On the other hand, one should take into account the complexity of the transition to solutions without the use of ready-made libraries. I wrote the same news site engine almost in one day. After all, among other things, "heavy" scripts not only require more powerful hosting, but also slow down the opening of the site's pages in the browser, especially if the page is formed within a few seconds. If it’s not very expensive for you to refuse to use ready-made libraries, I would advise you to do this anyway.

Summing up, I emphasize once again - you can safely use libraries, increasing the capacity of servers, but you should not forget that this is the first reason for the slow operation of your scripts, and in addition to the high load on the hardware, they are the cause of many delays in loading site pages.

2) Ignoring Zend Optimizer, eAccelerator

These great modules mainly deal with optimization and dynamic caching of compiled PHP code ( byte - code). Often allow you to increase productivity almost dozens of times. Their use makes sense, first of all, on fairly large and highly visited projects, although you can optimize any other sites in PHP - this will not require any additional manipulations from you. We will talk more about the use of these modules, next time, this is a rather voluminous topic. For now, you just need to remember this point.

3) "Crooked" use of databases

In fact, this is a separate issue. You should remember that every database connection, every query, every extra table in a query, etc. - all this creates a tangible burden. But still, the logic of the database itself, and not the interface for working with it, bears the greatest load. I recently had to optimize one very popular module for one of the most popular "engines" of the forum. As I immediately managed to find out - the same module was the main cause of significant brakes. By adding one small table and two new SQL queries in PHP code, forum performance has been increased by 60-80% (depending on the page), memory consumption has decreased by 5-7%! And it's almost all out of the blue. As you can see, this is the case when adding an "extra" table and "extra" queries significantly increases performance. I went not extensive, but intensive way, improving the logic. And with truly amazing results.

We will talk about database optimization in the near future. Now I will only touch on the aspect related to the interface of work, both in PHP and, by the way, in any other programming language.

So, first of all, always use files instead of a DB if that makes sense. When does it make sense? Let's say you're writing a news site engine. The news is added there once and for all. It is not subject to subsequent changes, it is large and solid. It is much easier and more efficient to put it in a separate file, rather than in a database. But the review of the news is already better in the database. Indeed, on certain pages you will obviously have to display a list of recent reviews on a topic, or a list of random reviews. If we write each review in a separate file, then when we display, say, 50 reviews per page, we will have to include the same number of corresponding review files. Writing all the reviews in the same file is also not very good: with a large number of them, the file will be very large, and will only grow over time, while the performance will decrease accordingly. Yes, and it can simply be quite inconvenient and unsafe business - working with such files. It’s another matter to “throw” our small reviews into the database and “pull out” the ones you need with one simple request. The same applies to any frequently edited data. For example, writing a news view counter on files is a big nonsense. DB only.

As for the connection to the database, it should be closed as soon as it is no longer needed. However, you should not do this if it is still useful in the work of this script.

Monitor the contents of variables that are assigned the results of query execution. It makes sense to use unset in situations where large amounts of data are no longer needed.

4) No caching

In a number of cases, caching is simply irreplaceable. Let's consider a simple example. A little higher, when it came to the database, I gave an example with a list of reviews. Suppose we go to a certain page that displays a list of 50 reviews of the latest news. As a rule, all of them can be selected from the database with one simple query. But on the other hand, we can create a file in advance that will contain all these 50 reviews in finished form. We will not need to select them from the database, format them according to our template and insert them in the right place on the page. We just immediately connect all this from a pre-generated file.

The essence of caching is to create a cache of the most frequently used and least frequently changed data. For example, how often do you have to update the cache of your 50 reviews? It is clear that every time new news is added - so that our cache displays up-to-date information. How often will new news be added? Let's assume that approximately every 15 minutes, i.e. up to 100 times per day. And what is the attendance of this site, how often are these reviews viewed? On the project, the “engine” of which I developed, about 70 thousand times a day. Thus, instead of performing a selection from the database, formatting and inserting these reviews 70 thousand times a day, it is usually performed no more than 100 times, the rest is just simple inclusions of completely finished data.

You should, whenever possible, create finalized data for caching, which is quite simple to connect to the page during the execution of the request, without the need for parsing, post-processing, templating, etc.

Do not forget that the cache does not have to be stored only in files and it is not necessarily possible to store only parts of our future HTML page in it. And especially if it is subject to frequent, systematic updates. For example, it is much more reasonable to keep a list of data about users who are online in the database, in a table of the Memory type.

5) Buffer, compression, frontend http server

Everything is very simple. During execution, all data that is displayed to the user is immediately sent to him. Roughly speaking, until the data is taken away, the continuation of code execution is not performed. So if in the process of work your script sends the finished HTML code through the echo function, for example, or by any other method, then the crypt transmits the data “in pieces”, each time “hanging”. It is much smarter to output data to the buffer, something like this:

php //initialize buffering
ob_start (); //execution of the script code
//... //finish buffering, fetch data
$html = ob_get_contents ();
ob_end_clean ();
exit( $html ); ?>

Enabling dynamic compression of finished HTML pages (

ob_start(`ob_gzhandler`);

) can compress them by an average of 20-60%, increasing download speed and reducing the number of "hanging" processes. Do you have a traffic limit on your hosting? Then dynamic page compression will bring double benefits.

Of course, it should be taken into account that buffering slightly increases memory consumption, while compression increases the load on the processor. But these sacrifices often more than pay off with an increase in speed. And not only the speed of creation, but also the speed of page loading.

Finally, a front-end http server can take the performance of your PHP scripts to the next level. The fact is that even with caching, the processes associated with the user's request will "hang" until the user accepts all the data (or until the time limit for this is reached). The essence of the frontend server is to immediately receive data, allowing you to immediately unload spent processes. It is a kind of link between the user and a rather "heavy" backend server - where your PHP scripts are executed. But due to its "lightness", the front-end server significantly reduces the resources consumed. Again, this is a very broad topic and we will cover it in more detail in the near future.

6) Total inclusion

Suppose you have created your "engine" in PHP, followed all the previous tips. It is almost inevitable that there will be many different inclusions: configuration files, functions, languages, etc. The bottom line is that even a regular inclusion of the same file with functions will require a lot of time and memory, even if there is no executable code besides the functions in the include, and not one of the functions is called.

But after all, the functions are the most diverse and specific. So putting the entire list of functions in one file and including it every time is not the best way out. For example, the site has user registration: for this, you can have a number of special functions that are used only during registration. So why put them in a common inclusion of functions that will be connected every time you access the pages of the site?

Don't neglect include optimization. Take out what is not applied universally in separate, specialized inclusions. Another example to reinforce. My favorite news site engine. The functions for adding news, comments, their control and pre-parsing take up about 1/3 of the code of the total number of functions. But how often are they needed? In 1 out of 100 queries? Or 1 in 200? Or even less often? So why load them every time? This can indeed significantly reduce the performance of your solutions.

7) Extra functionalization and OOP-thymism

Functions should only be used when it really makes sense. Let's remember the basic purpose of functions. It's nothing but takeaway

frequently used within one cycle of the program

parts of the code into a separate, common part. In principle, it makes sense to move the code to a “separate part” even when it is executed by some relatively unlikely event. For example, attaching a photo to a post on a forum. Moving the image loading and processing handler to a “separate part” will have a positive effect on performance, even if it is enclosed in a condition (the fact that the image is loaded). At the same time, if we need this “separate part” only once, it is better to execute it simply as code (include), and not as a function. Functions always require some additional resources. The same goes for OOP programming in PHP. OOP code consumes slightly more resources, so if OOP code formatting is not important to you, it is better to abandon it. I'm talking specifically about OOP formatting, since the OOP approach in PHP has little to do with the very concept of OOP programming. As well as PHP with a classical understanding of programming languages ​​and their tasks - which I wrote about at the beginning.

So you got acquainted with the 7 basic principles of productive PHP code. This is just--just the beginning. We still have a lot of interesting, more specific material on this topic ahead of us.

One of the main criteria for the success of any Internet resource is the speed of its work, and every year users become more and more demanding according to this criterion. Optimization of php scripts is one of the methods to ensure the speed of the system.

In this article, I would like to present to the public my collection of tips and facts on script optimization. The collection was collected by me for quite a long time, based on several sources and personal experiments.

Why a collection of tips and facts and not hard and fast rules? Because, as I have seen, there is no “absolutely correct optimization”. Many techniques and rules are contradictory and it is impossible to fulfill them all. You have to choose a set of methods that are acceptable to use without sacrificing security and convenience. I have taken an advisory position and therefore I have advice and facts that you may or may not follow.

To avoid confusion, I divided all the tips and facts into 3 groups:

  • Optimization at the level of logic and organization of the application
  • Code optimization
  • Useless optimization

The groups are allocated conditionally and some items can be attributed to several of them at once. The figures are given for the average server (LAMP). The article does not address issues related to the effectiveness of various third-party technologies and frameworks, as this is a topic for separate discussions.

Optimization at the level of logic and organization of the application

Many of the tips and facts related to this optimization group are very significant and give a very large gain in time.

  • Constantly profile your code on the server (xdebug) and on the client (firebug) to identify code bottlenecks
    It should be noted that you need to profile both the server and client parts, since not all server errors can be detected on the server itself.
  • The number of user-defined functions used in the program does not affect the speed in any way
    This allows you to use an infinite number of user-defined functions in the program.
  • Make active use of custom functions
    A positive effect is achieved due to the fact that inside the functions, operations are carried out only with local variables. The effect of this is greater than the cost of user-defined function calls.
  • It is desirable to implement “critically heavy” functions in a third-party programming language as a PHP extension
    This requires programming skills in a third-party language, which greatly increases the development time, but at the same time allows you to use tricks beyond the capabilities of PHP.
  • Processing a static html file is faster than an interpreted php file
    The difference in time on the client can be about 1 second, so a clear separation of static and PHP-generated pages makes sense.
  • The size of the processed (connected) file affects the speed
    Approximately 0.001 seconds are spent on processing every 2 KB. This fact pushes us to minimize the script code when transferring it to a production server.
  • Try not to constantly use require_once or include_once
    These functions should be used when it is possible to reread the file, in other cases it is desirable to use require and include .
  • When branching the algorithm, if there are constructions that may not be processed and their volume is about 4 KB or more, then it is more optimal to include them using include.
  • It is advisable to use validation of sent data on the client
    This is due to the fact that when validating data on the client side, the number of requests with incorrect data is drastically reduced. Client-side data validation systems are built primarily using JS and hard form elements (select).
  • It is desirable to build large DOM constructs for data arrays on the client
    This is a very effective optimization technique when dealing with displaying large amounts of data. Its essence boils down to the following: an array of data is prepared on the server and transferred to the client, and the construction of DOM structures is provided to JS functions. As a result, the load is partially redistributed from the server to the client.
  • Systems built on AJAX technology are much faster than systems that do not use this technology.
    This is due to a decrease in withdrawal volumes and a redistribution of the load on the client. In practice, the speed of systems with AJAX is 2-3 times higher. Comment: AJAX, in turn, creates a number of restrictions on the use of other optimization methods, such as working with a buffer.
  • When receiving a post request, always return something, even a space
    Otherwise, an error page will be sent to the client, which weighs several kilobytes. This error is very common in systems using AJAX technology.
  • Getting data from a file is faster than from a database
    This is largely due to the cost of connecting to the database. To my surprise, a huge percentage of programmers maniacally store all data in a database, even when using files is faster and more convenient. Comment: files can store data that is not searched, otherwise a database should be used.
  • Do not connect to the database unnecessarily
    For a reason unknown to me, many programmers connect to the database at the stage of reading the settings, although they may not make further queries to the database. This is a bad habit that costs an average of 0.002 seconds.
  • Use a persistent database connection with a small number of simultaneously active clients
    The benefit in time is caused by the absence of costs for connecting to the database. The time difference is approximately 0.002 seconds. Comment: with a large number of users, persistent connections are undesirable. When dealing with persistent connections, there must be a mechanism for terminating connections.
  • Using complex database queries is faster than using a few simple ones
    The time difference depends on many factors (data volume, database settings, etc.) and is measured in thousandths, and sometimes even hundredths, of a second.
  • Using DBMS side calculations is faster than PHP side calculations for data stored in the database
    This is due to the fact that for such calculations on the PHP side, two queries to the database are required (getting and changing data). The time difference depends on many factors (data volume, database settings, etc.) and is measured in thousandths and hundredths of a second.
  • If the sample data from the database rarely changes and many users access this data, then it makes sense to save the sample data to a file
    For example, you can use the following simple approach: we get the sample data from the database and save it as a serialized array to a file, then any user uses the data from the file. In practice, this optimization method can give a multiple increase in the speed of script execution. Comment: When using this method, it is required to write tools for generating and modifying the data stored in the file.
  • Cache data that rarely changes with memcached
    The gain in time can be quite significant. Comment: caching is effective for static data, for dynamic data the effect is reduced and may be negative.
  • Working without objects (no OOP) is about three times faster than working with objects
    Memory is "eaten up" also more. Unfortunately, the PHP interpreter can't handle OOP as fast as regular functions.
  • The higher the dimension of arrays, the slower they work.
    The loss of time arises from the processing of the nesting of structures.

Code optimization

These tips and facts give a slight increase in speed compared to the previous group, but taken together, these techniques can give a good gain in time.

  • echo and print are significantly faster than printf
    The time difference can be up to several thousandths of a second. This is because printf is used to output formatted data, and the interpreter checks the entire line for such data. printf is only used to output data that needs formatting.
  • echo $var."text" is faster than echo "$var."text"
    This is because the PHP engine in the second case is forced to look for variables inside the string. For large amounts of data and older versions of PHP, time differences are noticeable.
  • echo "a" is faster than echo "a" for strings without variables
    This is because in the second case the PHP engine is trying to find the variables. For large amounts of data, the differences in time are quite noticeable.
  • echo "a","b" is faster than echo "a"."b"
    Comma-separated data output is faster than dot-separated data. This is because string concatenation occurs in the second case. For large amounts of data, the differences in time are quite noticeable. Note: this only works with the echo function, which can take multiple lines as arguments.
  • $return="a"; $return.="b"; echo $return; faster than echo "a"; echo "b";
    The reason is that the data output requires some additional operations. For large amounts of data, the differences in time are quite noticeable.
  • ob_start(); echo "a"; echo "b"; ob_end_flush(); faster than $return="a"; $return.="b"; echo $return;
    This is because all the work is done without accessing variables. For large amounts of data, the differences in time are quite noticeable. Comment: this technique is not effective if you are working with AJAX, since in this case it is desirable to return the data as a single line.
  • Use "professional insert" or? > a b
    Static data (outside code) is processed faster than PHP output. This technique is called professional insertion. For large amounts of data, the differences in time are quite noticeable.
  • readfile is faster than file_get_contents , file_get_contents is faster than require , and require is faster than include to output static content from a single file
    The time to read an empty file fluctuates from 0.001 for readfile to 0.002 for include .
  • require is faster than include for interpreted files
    Comment: when branching the algorithm, when it is possible not to use the interpreted file, you must use include , because require always includes a file.
  • if (...) (...) else if (...) () is faster than switch
    The time depends on the number of branches.
  • if (...) (...) else if (...) () is faster than if (...) (...); if(...)();
    Time depends on the number of branches and conditions. You should use else if wherever possible, as it is the fastest "conditional" construct.
  • The most common conditions of the if (...) (...) else if (...) () construct should be placed at the beginning of the branch
    The interpreter scans the structure from top to bottom until it finds a condition. If the interpreter finds that the condition is met, then it does not look at the rest of the structure.
  • < x; ++$i) {...} быстрее, чем for($i = 0; $i < sizeOf($array); ++$i) {...}
    This is because in the second case, the sizeOf operation will be executed on each iteration. The execution time difference depends on the number of array elements.
  • x = sizeOf($array); for($i = 0; $i< x; ++$i) {...} быстрее, чем foreach($arr as $value) {...} для не ассоциативных массивов
    The time difference is significant and increases as the array grows.
  • preg _replace is faster than ereg_replace , str_replace is faster than preg_replace , but strtr is faster than str_replace
    The time difference depends on the amount of data and can reach several thousandths of a second.
  • String functions are faster than regular expressions
    This rule is a consequence of the previous one.
  • Delete already unnecessary array variables to free up memory.
  • Avoid using error suppression @
    Error suppression produces a number of very slow operations, and since the repetition rate can be very high, the speed loss can be significant.
  • if (isset($str(5))) (...) is faster than if (strlen($str)>4)(...)
    This is because the standard isset check operation is used instead of the string function strlen .
  • 0.5 is faster than 1/2
    The reason is that in the second case, a division operation is performed.
  • return is faster than global when returning the value of a variable from a function
    This is because in the second case a global variable is created.
  • $row["id"] is faster than $row
    The first option is 7 times faster.
  • $_SERVER['REQUEST_TIME'] is faster than time() for determining when a script should run
  • if ($var===null) (...) is faster than if (is_null($var)) (...)
    The reason is that there is no use of a function in the first case.
  • ++i is faster than i++ , --i is faster than i--
    This is due to a feature of the PHP core. The time difference is less than 0.000001, but if you have these procedures repeated thousands of times, then take a closer look at this optimization.
  • Increment of initialized variable i=0; ++i; faster than uninitialized ++i
    The time difference is about 0.000001 seconds, but due to the possible repetition frequency, this fact should be remembered.
  • Using "used" variables is faster than declaring new ones
    Or to rephrase it differently - Do not create unnecessary variables.
  • Working with local variables is faster than with global ones by about 2 times
    Although the time difference is less than 0.000001 seconds, due to the high repetition rate, you should try to work with local variables.
  • Accessing a variable directly is faster than calling a function within which this variable is defined several times
    It takes about three times more time to call a function than to call a variable.

Useless optimization

A number of optimization methods in practice do not have a great impact on the speed of script execution (time gain is less than 0.000001 seconds). Despite this, such optimization is often the subject of controversy. I brought these "useless" facts so that you do not pay special attention to them when writing code later.

  • echo is faster than print
  • include("absolute path") is faster than include("relative path")
  • sizeOf is faster than count
  • foreach ($arr as $key => $value) (...) is faster than reset($arr); while (list($key, $value) = each ($arr)) (...) for associative arrays
  • Uncommented code is faster than commented code because it takes extra time to read the file
    It is very stupid to reduce the volume of comments for the sake of optimization, you just need to minimize it in working (“combat”) scripts.
  • Variables with short names are faster than variables with long names
    This is due to the reduction in the amount of code being processed. Similar to the previous point, you just need to minimize it in working (“combat”) scripts.
  • Code markup using tabs is faster than using spaces
    Similar to the previous point.

Finally, I want to remind you once again that the advice and facts I have given are not absolute and the significance of their application depends on the specific situation. It must be remembered that script optimization is only a small part of the entire optimization procedure and it is often possible to live without the above tips.


If you have any questions, please use our

  • How to optimize the site and speed up its work?
  • How fast will the site work and can it work, in accordance with the technologies on which it will be launched?
  • What technologies should be used when setting up a server or VPS?

Typical problem:
At some point, the site starts to open and work too slowly. It happens that the hosting company blocks the site for exceeding the load or overusing resources. What to do in such a situation?

Maybe the site has become too popular, or some resource-intensive module has been installed, an attack is being made, or the site is infected with a virus. One way or another, but all these cases have something in common and this is a problem of all sites on all hostings.

And if we talk about servers for PHP, then such a problem is the way the php code is executed, just like other significant environment settings on the server.
Regardless of whether there is a problem in your code or not, whether your attendance is high or not, a lot depends on the server settings. So that everything said does not sound like empty words, this article was written.

In this review, I will test a newly installed site on one of the most common content management engines. Drupal 7.33.

For the test, only one component of php-hosting was selected. We will test web servers Nginx And Apache2, modules mod_php And php-fpm, php versions php53 And php56, let's see how optimizers affect apc And opcache on site speed.


Of course, these parameters are only a part of the settings on which the speed of the site depends. But we deliberately
we limit ourselves to this, so as not to make the review endless.

Given:
  • Operating system Centos 6.7
  • Database Server: MariaDB 10.21
  • All site sessions are stored in memcache to remove the influence of session setup speed on site speed.
  • In all tests, the nginx 1.93 web server acts as a frontend. In the case of Apache2, Nginx acts as a load balancer as well as serving up static. In configurations without using Apache2 - the direct web server is Nginx
  • The Nginx and MariaDB configuration contain many optimizations aimed at achieving maximum performance, but for all test participants these settings are the same and therefore their influence should be neglected
  • The opcache and apc parameters are taken from Bitrix recommendations, as they are optimal and universal for most sites
How will we test?

There is a zabbix server on the local network and its tasks every minute:

  • Open the main page of the site under test, wait for certain content on the page, verify that the response from the server is a 200 code.
  • The next step is authorization in the site admin panel, this happens by sending the corresponding POST request. Verification of the text and response code on the page with the established standard. This step affects almost all subsystems of the web server, and in many respects its speed depends on the speed of interaction with the database
  • The last step is to log out of the site admin area, verify the response code and the text on the exit page
  • At the end of each step, zabbix will meticulously measure and record the rendering speed of the php code in html understandable to the browser and show us graphs of the results
  • For each subject, values ​​will be recorded for one hour and the result will be the average values ​​for that hour.
  • Testing will take place within the local network, so the impact on the result of the speed of the Internet connection is excluded
  • For ease of perception, all results are shown in ascending order. Those. the very first result is the slowest. All configurations were placed under a conditional number, this will allow you to better navigate the results
  • Upper graphs - code generation speed, the higher the value, the better. The lower graphs are the server response time and the lower the value, the better
  • Tested sites live their own lives, they have regular database operations and scheduled tasks, which is why the curve on the graphs can have ups and downs

Testing:

1. Nginx + php-fpm56 without opcache optimizer

Architecturally, this is one of the most advanced options. In terms of performance - the biggest disappointment.

Performance leaves much to be desired, but this option will withstand the load much better than option #2 with Apache2. Also, this option will consume RAM much more efficiently.

2. Apache2 + mod_php53 without apc optimizer

The most typical option for hosting. 90% of popular hosting providers use this option. Although php53 has not been supported by developers for a long time, there are a lot of sites on the Internet that still work on this version.

This option is not only very slow, but also quickly crashes under light load due to lack of Apache2 worker processes, or due to lack of RAM on the server.

3. Balancing and statics via Nginx, dynamic part of Apache2 + mod_php56 without opcache optimizer

This option was created as a solution for modern sites. It is offered by hosting companies that strive to provide the latest version of PHP. According to popular belief, this version of PHP should be faster and more secure than the previous ones.

Unfortunately, not all sites can work fully with this version. Almost every new version of PHP stops supporting some deprecated and "unsafe" features, breaking the "old" code.
By itself, php56 without an optimizer is quite slow, and mod_php tends to crash and take up all the memory on the server under load.

4. Nginx + php-fpm53 without apc optimizer

Enough advanced configuration for those who do not want to have problems due to errors with the code optimizer. This uses a "compatible" version of the PHP interpreter, and also removes the resource-intensive Apache2 from the bundle.

5. Balancing and statics through Nginx, dynamic part of Apache2 + mod_php53 + apc

Another common variation. A lot of hosting companies use it, and either use it by default or allow you to enable the optimizer in their control panels.
Usually Apache2 is left to handle .htaccess rules like link translation and CNC.

We get a speed increase of 3.5 times, compared with the option without using the optimizer.
Apache itself (when using its own mod_php module) consumes much more resources to run than the php-fpm version. Apache2 tends to crash if one of its modules fails or fills up all the server's RAM.

6. Nginx + php-fpm53 + apc

A great option for sites on older engines that do not require complex .htaccess

This is the option I use when it is necessary to raise an outdated site, achieve satisfactory speed from it and reliable operation under high loads.

7. Balancing and statics through Nginx, dynamic part of Apache2 + php-fpm53 + apc

Option for legacy sites with complex .htaccess. For example, old Bitrix installations.

This is ideal for legacy sites. This configuration is resistant to high loads, compatible and sufficiently productive.
Great for when you need .htaccess rules and additional Apache2 modules.
Of the shortcomings - an outdated and not updated version of php, but if there is no choice, this is the best option. Great for old versions of Bitrix, Joomla and other common CMS not the latest versions.

8. Balancing and statics through Nginx, dynamic part of Apache2 + mod_php56 + opcache

Sufficiently productive, but resource-intensive configuration with all the shortcomings of mod_php.

Fast enough, but under load, the server may run out of memory, and the speed will drop significantly.

9. Nginx + php-fpm56 + opcache

The most productive option.

This is the best option for all modern sites. Holds the load well, shows the best result in terms of performance. This is the option I use when the task is to optimize the performance of the site and increase the speed of its work.
The only downside is that we won't be able to use .htaccess and all mod_rewrite rules need to be rewritten to Nginx syntax.
Apache2 modules will also not work. If those are used, then this option will not work.

10. Balancing and statics via Nginx, dynamic part of Apache2 + php-fpm56+ opcache

The best option for sites that need .htaccess. Ideal for fresh versions of Bitrix.

Holds the load well due to php-fpm. I actively use this option for most sites.

Main page of the test site
Configuration number Architecture Average response ms.
1 77,04 103,6
2 78,79 103,98
3 78,85 102,38
4 81,55 97,88
5 Apache2 + mod_php53 + apc 303,37 29,36
6. nginx + php-fpm53 + apc 312,33 24,73
7. Apache2 + php-fpm53 + apc 339,63 23,32
8. 484,96 16,91
9. nginx + php-fpm56 + opcache 546,34 14,08
10. Apache2 + php-fpm56 + opcache 571,14 13,78
Authorization in the admin panel of the test site
Configuration number Architecture Average download speed kb. Average response ms.
1 Nginx + php-fpm56 without opcache optimizer 67,51 239,01
2 Apache2 + mod_php53 without apc optimizer 64,61 257,51
3 Apache2 + mod_php56 without opcache optimizer 66,75 242,42
4 Nginx + php-fpm53 without apc optimizer 68.79 233.15
5 Apache2 + mod_php53 + apc 173,81 94,26
6. nginx + php-fpm53 + apc 173,3 91,3
7. Apache2 + php-fpm53 + apc 182,1 90,5
8. Apache2 + mod_php56 + opcache 218,35 77,55
9. nginx + php-fpm56 + opcache 252,83 62,25
10. Apache2 + php-fpm56 + opcache 262,8 60,85
Logging out of the admin panel of the test site
Configuration number Architecture Average download speed kb. Average response ms.
1 Nginx + php-fpm56 without opcache optimizer 41,01 184,49
2 Apache2 + mod_php53 without apc optimizer 42,42 188,97
3 Apache2 + mod_php56 without opcache optimizer 42,06 188,37
4 Nginx + php-fpm53 without apc optimizer 45,48 169,15
5 Apache2 + mod_php53 + apc 190,1 41,87
6. nginx + php-fpm53 + apc 185,92 41,24
7. Apache2 + php-fpm53 + apc 202,78 39,21
8. Apache2 + mod_php56 + opcache 315,56 26,23
9. nginx + php-fpm56 + opcache 373,19 20,43
10. Apache2 + php-fpm56 + opcache 381,21 20,57

As a summary:

  • In real life, all Apache2 options can be slower, because in my tests I intentionally passed the Nginx static feed back. This is done to exclude the influence of the speed of static return on the results of measuring the speed of the PHP interpreter. One of the weakest side of Apache2 and at the same time the strongest side of Nginx is the speed of uploading statics. This is especially noticeable at high loads. In addition, Nginx is less susceptible to "slow connections" attacks.
  • mod_php consumes all available server memory very quickly and loses performance on loads
  • php-fpm is much more memory efficient, safer, and more flexible in its settings. In some cases, it is faster and without high loads.
  • The test has a narrow specificity, here we saw the features of the Drupal engine, others may behave differently, but the general trend will be the same.

And most importantly, the speed of your site depends on the configuration of your server or hosting. By choosing the right architecture, you can get a fivefold increase in site speed.

If you have questions, difficulties or need advice:
My contacts in



Liked the article? Share it