Many organizations treat performance optimization as an afterthought when developing PHP applications. After all, stakeholders are more concerned with getting something up and running than spending time ensuring that every database query is optimized and every page is properly cached.
Performance problems don’t become a concern until users start noticing significant slowdowns or infrastructure bills start increasing out of control. The original developers may be long gone and new managers might not know where to start with diagnosing and solving these issues.
There are many performance optimization tools out there to help you identify problems, but actually solving them requires knowing what problems to look for and how to resolve them.
In this article, we will take a look at how to identify and address common performance bottlenecks in PHP applications.
Lack of caching strategy
Imagine that you have a PHP content management system that powers a news website. Each time a visitor clicks on a story, a database query is executed to retrieve the story content. It’s easy to see that thousands of visitors to hundreds of stories could put considerable strain on a database.
Since a story’s content doesn’t change once it’s published, you could store the result of the first query into a temporary HTML file that can be served to subsequent visitors reaching the same story. The HTML file can be served in a fraction of the time, without requiring a separate database query.
This is a high-level example of a caching strategy known as content caching. These strategies are simply efficient ways to store frequently used resources.
There are also lower-level caching strategies:
- Memcache: Memcache lowers database load by storing arbitrary data from the results of database calls, API calls, or page rendering in memory as a key/value pair.
- Opcode: Opcode caching optimizes code performance by keeping a copy of compiled code in memory, so identical PHP code isn’t recompiled every time a request is made.
There are many different caching tools available for PHP developers, but Memcache and Alternative PHP Cache (APC) are the most popular low-level caching tools.
Poorly written queries
Suppose that you have a PHP content management system and you want to show users a list of recent articles. You could use a simple SQL query, `SELECT * FROM articles ORDER BY date ASC`, and select five recent articles in PHP using `array_slice($array, 0, 5)`. The problem is that you are selecting all of the articles in the database, which takes a lot of time and degrades performance.
When a user clicks on an article, suppose that you want to show its author. You could run a separate SQL query, `SELECT * FROM authors WHERE id = $author_id`, and show the author’s name. The problem this time is that you’re running two separate SQL queries when showing a single page, which could further increase loading time and hurt the application’s performance.
A better approach is to limit the SQL query: `SELECT title, url FROM articles ORDER BY date ASC LIMIT 5`. This query will take a lot less time to execute since it’s pulling only five records from the database. You could then pull the article content *and* the author information using a single `LEFT JOIN` query to avoid making multiple database queries.
These are just two common examples of poorly written SQL queries and how to refactor them, but there are thousands of different instances where queries can be improved. You can find these problems by looking at SQL logs to identify slow queries and address them before they become problems.
In addition to rewriting queries to be more efficient, you can add indexes or (re-)cluster tables to speed up database performance independent of these queries.
External API issues
Many modern web applications rely on third-party APIs. For example, an application may rely on an email server to send transactional emails; a payment processor to process orders; or, a content delivery network (CDN) to host images. A slowdown in these services could slow down your application.
There are two strategies to resolve these issues:
- Cache API Output: Memcache can be used to cache API output, which reduces the number of API calls, as well as reduces the likelihood of an API-related slowdown.
- Background Processes: API calls should be made with background processes and reasonable timeouts. If an API call fails in the background, the application should show some kind of output to the user without the response.
It’s a good idea to audit your PHP application early on to determine what third-party APIs are being used. That way, you can easily determine if there’s an issue, keep on top of updates to the API over time, and explore alternative options if the issues cannot be resolved.
No profilers or tooling
Performance monitoring software may not be a fix-all, but it definitely helps quickly identify and diagnose problems.
Retrace is one of the most common PHP performance monitoring tools on the market. Unlike many other APMs, Retrace provides app performance monitoring, code profiling, error tracking, centralized logging, and app/server metrics to identify bottlenecks across the stack.
There are also some open source solutions to assist with performance monitoring. For example, PHP Server Monitor provides some basic reporting that can help identify issues, and it doesn’t involve a monthly cost since it’s hosted on your own servers.
The bottom line
Performance issues tend to arise in older PHP applications that haven’t been well maintained over time. If you’re experiencing these issues, it’s important to identify and address the root causes. We have discussed many of the most common causes in this article, but there are countless others that can arise.
If you’d like to see if Siftware is a good fit for you and your project, please don’t hesitate to get in touch.