Troubleshooting Performance with PHP on IBM i
So you have a PHP application running on your IBM i, but you’re starting to get complaints about performance. What do you do? Where do you look? Hopefully some of the tips below can give you a head start.
Don’t Jump to Conclusions!
First and foremost, don’t jump to conclusions about the cause of the performance issue. So much time can be wasted going down the wrong path.
Below are some great tools and techniques to help you find your performance bottlenecks. If you have them, use them – the information they provide is invaluable.
Tools / Technique
ZendServer Web Interface
If you have a paid subscription or trial for ZendServer, you have access to the ZendServer web interface, which has a wealth of information. Make sure the ZendServer apache instance is running (ZENDSVR6 or ZENDPHP7).
In regard to performance, this interface can tell you which pages are taking the longest, which pages are used the most, and even give you a stack trace to see where the time is being spent.
Z-Ray is an additional ZendServer tool and can be turned on through the ZendServer web interface. Z-Ray provides a developer toolbar that appears inside your browser window. It can show you exactly how long the current page took, including a breakdown of time taken for PHP processing, database access and rendering. It will also show information on each ajax call. And my favorite is a list of all the database queries for the current page and their performance. I am often surprised how many queries are done for one page.
Don’t have any of the above tools? You can always use PHP to determine performance bottlenecks. Though it takes more time to diagnose, you can use code like the snippet below to collect exact timing information. I prefer logging into the database myself, so I can collect performance averages, and other useful information. You can also code this in such a way that performance logging can be turned on and off based on a debug flag.
Your apache access and php error logs also provide a wealth of information. Review your error logs often for clues to existing issues. Access logs can also be very useful in determining often-used pages that may be creating a load on the server. For example, be careful using too many frequent ‘ping’ requests to the server. Even if these calls are small and fast, if they are done too often they can slow down response time for the entire application. There are many tools available to import and analyze your logs.
PHP logs can fill up fast and become quite large. Once this happens, opening the log to write to it can cause a performance issue itself. Try to rename your php error log on a regular basis.
You Found the Bottleneck – What Now?
OK! So you’ve found your bottleneck. What can you do about it? Below are some common issues and fixes that I run into.
High on the list of performance issues is database queries. Too many queries or overly complex queries on a page can slow it down. Be on the lookout for queries done within a loop and see if there is a way to rework your structure to eliminate this need – an additional join perhaps.
Review your SQL to see if there is a simpler way to write your queries.
If you have an older OS, avoid writing queries that need to use the older ‘Classic Query Engine’ (CQE). For more information, review the query dispatcher documentation for your OS – for example:
Use Index Advisor
Once you have finalized the queries you will use, run them through the ‘Index Advisor’ in your ‘IBM i Access Client Solutions’ tool. Start with ‘Run SQL Scripts’, enter in your query and click ‘Visual Explain’. This will show you how your query will be executed. Then select ‘Index Advisor’ from the menu and it will provide you with a list of indexes that could improve performance of that query. It will even create them for you or generate the SQL source.
Use ajax on your page to load different pieces that may be time consuming. A user is more forgiving of performance issues if they see things changing on their screen. Remember to use a visual indication, like a spinner, that something is loading.
Turn on compression in your apache server. This will help speed up the transfer time of data between the server and client.
Caching is your friend. If processing doesn’t need to be repeated, then don’t repeat it. But put some thought into what should and should not be cached. Is this a piece of data that won’t often be updated?
ZendCache is another useful tool to cache data within PHP. It can be useful to cache information you may have fetched from a database or a web service call and that you don’t need to update often.
Is the slow-down within the PHP code? Loops are fundamental for programming but be mindful of what you put inside loops. It’s a big red flag if there is a lot of processing within a loop that might be executed hundreds of times. The biggest culprits are database queries and RPG/CL calls.
Not everything has to be supplied to the client interactively. You may have some processing-intense operations that would be better off submitted as a batch process. An example I often run across is PDF generation. Once the processing is done, send the user a notification in the browser, or via email. You can even submit PHP to batch from PHP:
Whenever possible, keep your tools up-to-date to take advantage of any performance improvements made. This could include PHP and ZendServer, any third-party tools you are using and your IBM i itself.
I hope some of the above tips can help you get the most out of your PHP application and save you time and headaches.