Industry analysts have been predicting the demise of PHP for years. But PHP continues to rank high in various programming language popularity indexes and it is used by almost eight out of 10 websites, powering a significant portion of the internet, from Wikipedia to content management applications like WordPress and Drupal, which have been deployed millions of times.
PHP offers an easy-to-understand programming model for web developers. It makes iterative development and debugging simple, yielding a big productivity boost. Historically, though, PHP has gotten a bad reputation for slow performance and security issues, leading to questions about its future as a programming language.
With Sentry Performance Monitoring for PHP, developers can now quickly discover performance issues with their PHP-based applications. Within minutes, they can trace issues back to a poor-performing API call or slow database query and surface trends to help them proactively prevent future performance issues, saving time and reducing costs.
Distributed tracing for PHP applications
PHP applications consist of interconnected components, such as the front end (single-page application), back end (REST API), task queue, database server, and cron job scheduler. Each can be instrumented to capture error data or crash reports, but that doesn’t provide developers with the full picture, as each piece is analyzed separately. With Sentry Performance Monitoring for PHP, distributed tracing allows developers to tie all of the data together to gain clearer insights into which services may be having a negative impact on the application’s overall performance.
A distributed trace represents the record of the entire operation that is measured or tracked, such as page load time, or an instance of a user completing some action in the application, or a cron job in the back end. And each trace consists of one or more tree-like structures called transactions, the nodes of which are called spans. In most cases, each transaction represents a single instance of a service being called, and each span within that transaction represents that service performing a single unit of work, whether that is calling a function within that service or making a call to a different service. Here’s an example trace, broken down into transactions and spans:
Because a transaction has a tree structure, top-level spans can be broken down into smaller spans, mirroring the way that one function may call a number of other, smaller functions. This is expressed using the parent-child metaphor, so that every span may be the parent span to multiple child spans. Here’s a zoomed-in view of one of the transactions from the diagram above:
Real-time metrics for PHP applications
By identifying useful thresholds to measure PHP applications, developers can more easily identify when errors occur or if performance issues are emerging. With Sentry Performance Monitoring for PHP, real-time metrics enable developers to quickly understand customer satisfaction based on the application’s response time to their interactions. Let’s take a look at some of those metrics:
- Apdex: Apdex is an industry-standard metric used to track and measure user satisfaction based on application response times. It provides a standard for developers to compare transaction performance, understand which transactions may require additional optimization or investigation, and set targets or goals for performance.
- Failure rate: indicates the percentage of unsuccessful transactions.
- Throughput data: indicates the number of transactions over a given time range, average transactions per minute, or average transactions per second.
- Latency: indicates the average response time for all occurrences of a given transaction.
- Frequency: aggregate transaction counts and the rate at which transactions are recorded.
- User misery: a user-weighted performance metric to assess the relative magnitude of an application’s performance.
Now that developers are able to trace the exact issues causing performance bottlenecks in PHP applications, let’s look at five common mistakes developers make when creating PHP applications and how they can solve them.
Mistake #1: Making too many database queries
PHP runs into the same kind of constraints that developers would have with other languages, such as too many database queries. Developers aren’t database experts. Most are not well-versed in all the nuances of the database they’re using. Oftentimes, they’re not using their database access layer optimally so they end up doing too many database queries or generating database queries that don’t use indexes.
Databases also perform differently under different load types. A database running on a laptop with tens of megabytes of memory behaves differently than a production database with a gigabyte as different strategies are used to select which data to look at. Queries that worked on a developer’s local machine or staging environment can perform differently in production.
The mitigations to poor database query performance are to add caching and tuning queries. Caching helps reduce the number of queries sent to the database when the result is already known or frequently accessed. For example, the “newest” article in a news site changes less frequently than it is read. By caching the results, developers can improve performance by reading results from the cache instead of the database. Tuning database queries usually involves adding additional indexes on data that is frequently used in conditions or joins. It can also involve storing data in ways that require fewer joins to access.
Mistake #2: Loading too many files
With other programming languages, applications boot up and then keep the code and associated data in memory. With PHP, however, there is no persistent application state—files are reloaded on every request. When developers don’t account for this, they can run into the issue of loading too many files, which consumes a system’s resources and slows down performance.
Developers can solve this problem by turning on operation code (opcode) caching. Like many languages, PHP processes source code into opcodes, which are then executed in the PHP runtime. Converting PHP code to opcodes happens on each request, as PHP has no shared state. While parsing source code and generating opcodes is relatively cheap, the costs add up as an application handles more traffic. By enabling opcode caching, the source code parsing step can be skipped, yielding measurable performance gains.
Mistake #3: Misconfiguring the web server
Unlike other programming languages in which the web server is part of the language, PHP runs inside of a web server. Apache HTTP Server and Nginx are the two most commonly used. The web server is another layer PHP developers need to oversee. From picking a process model in Apache to tuning PHP-FPM (Fast Process Manager) when using Nginx, there are a few tuning options to use.
For example, developers will need to configure the number of worker processes to create, and how often to recycle them. If they don’t have enough workers available, their users will have to queue up and wait for a worker to become free. If they have too many workers, they could run out of memory during a busy time. Developers can use the amount of memory an application typically uses and the resources available on their servers as a guide for choosing the number of workers.
Mistake #4: Poor security practices
PHP allows developers to combine a variety of programming paradigms and switch between HTML and PHP code fluidly. Without rigor, this can quickly result in messy code that is hard to maintain. This flexibility is one of the reasons that PHP is an excellent language for beginners, but it can easily become a weakness that may expose the applications to security issues like cross-site scripting (XSS) and SQL injection (SQLi).
Developers can mitigate these risks by using mature frameworks, tools, and libraries. Using a templating library like Twig helps prevent cross-site scripting by automatically HTML encoding all variables that are displayed in templates. Using an object relational mapper (ORM) or database abstraction library can prevent SQL injection by using prepared statements.
Mistake #5: Failing to use strict types and type hinting
PHP has a forgiving type system. Historically, PHP has favored coercing types over creating errors. This can lead to traps like dividing numbers by words and getting “useful” results, but also creating runtime errors. To help prevent these kinds of mistakes, developers should enable “strict_types” and use tools like Psalm and PHPStan as part of their development process. These tools analyze code statically, and by looking at what types of data are being used across their application, they can point out potential problems before they become actual problems that impact users.
Sentry Performance Monitoring for PHP can help developers identify common performance problems as described above. These types of performance bottlenecks and code errors can drive unsatisfied customers directly to the competition. Without context into what’s causing the issue, developers waste valuable time blindly following different trails. It’s costly. Studies show that organizations spend about $4.6 million annually on incident management. Sentry arms developers with additional insight on the health of an application to improve the user experience.
Mark Story is a principal developer at Sentry, an application monitoring software company that helps developers discover, triage, and prioritize code errors and performance bottlenecks in real time.
New Tech Forum provides a venue to explore and discuss emerging enterprise technology in unprecedented depth and breadth. The selection is subjective, based on our pick of the technologies we believe to be important and of greatest interest to InfoWorld readers. InfoWorld does not accept marketing collateral for publication and reserves the right to edit all contributed content. Send all inquiries to [email protected]
Copyright © 2021 IDG Communications, Inc.