An Introduction To Performance And Dynamic Websites

A couple of weeks ago I shared some performance tests for server response time as well as Speed Index and time to first byte that I ran on this site before and after moving to a new web host. The posts were part of an on-again off-again series about website performance that I’ve been running the last year or so. In every post up to this point I’ve talked as though all sites were built in fundamentally the same way. As you know, not all sites are built in the same way.

Two major classes of sites, as far as performance is concerned, are static and dynamic. The big difference is that dynamic sites are built on the fly. The page that displays in the browser doesn’t exist as a single file. Instead, it’s programmatically generated when requested. Dynamic pages run server side code that calls other files, and queries databases to gather all the parts necessary for assembly.

Dynamic pages are converted into static HTML pages that are ultimately delivered across the network, but they naturally have more work to do during the conversion and consequently take more time to finally reach their destination after being requested.

I want to pick up the series again spend some time talking about dynamic web pages and some of the specific performance issues they face and how you can improve that performance. Because I’m most familiar with PHP and MySQL and because the odds are it’s the same for you, I’ll focus the series on both, but know that much of what’s true for each is also true for other languages and databases. The specifics might change, but the general ideas are the same.

The Critical Path

I’ve started a number of these mini-series with a quick mention of the critical path, which are the things that need to happen before a web page can load in your browser after you request it.

  1. DNS Lookup
  2. Browser sends an HTTP request
  3. Server responds and sends back the requested HTML file
  4. Browser begins to render HTML
  5. Browser sends additional requests for objects embedded in the html file (CSS files, images, javascript, etc.)

The first three steps in the path lead to the time to first byte (TTFB).

There’s no difference in the first two steps of the path for static and dynamic sites. It’s in the third step where you see a difference. Again it’s ultimately an HTML page that’s delivered over the web, but the server needs to do a little more work and take a little more time to generate that HTML page.

Somewhere in the server responds part of step three, the server converts dynamic code into static HTML. How does it do that?

Requests for Dynamic Pages

What happens when a dynamically built page is requested? Again the first two steps in the critical path are the same. There’s a DNS lookup and then an HTTP request is sent for the page.

If the URL in question is for a static page, the server grabs the file and sends it back to the browser making the request, which then makes additional requests for CSS and Javascript and images and other media. If the site runs over HTTP/2 some of these additional resources are delivered before being requested.

If the URL in question is for a dynamic page, the server needs to execute the server side code to build the HTML page that will be delivered. The requested file is run through an interpreter or parser. The code executes and possibly queries the database to find the specific content to be displayed.

Consider a very simple example:

<!doctype html>
<html lang="en">
 <title>Page Title</title>

 <p><?php echo "Some content here" ?></p>

It’s a simple page with a single line of PHP to echo some text on the page. I even included the the text to echo to make it as simple as possible and yet, as simple as it is, the one line of PHP code means the file needs to run through an interpreter, which takes some amount of time no matter how much.

The page you’re reading now is another example. There’s no actual file at the URL Instead PHP code in WordPress and the PHP engine do their thing to figure out what content should be displayed at that URL. They find all the parts from the file system and database that are needed to assemble the page and put all the parts together and convert everything into HTML (and CSS and Javascript) and the page was sent to your browser.

It all happens faster than it took me to type our what happens, but it’s still slower than if everything were already included directly in a single file without any need to run code through a runtime engine.

As you would expect, static pages load faster than dynamic ones since they don’t need to be sent elsewhere to execute code and since they don’t need to connect to a database, query it, and wait for the database to return results.

However, the odds are your site is dynamic, possibly on WordPress like mine. What can we do to speed up the execution time of the code? What can we do to speed up how quickly the code can get results from a database? Let’s focus on the code, specifically PHP for now and in a few weeks I’ll get to the database.

How the Zend Engine Works

The default PHP interpreter is the Zend Engine. It reads your PHP code and converts it into an abstract syntax tree (AST), which is translated into something called opcodes. Opcodes are execution units for the Zend Virtual Machine.

Opcodes are low level in that they’re closer to the machine code the server hardware understands as opposed to the higher level abstraction of PHP that’s easier for you and me and every other person to read and work with.

The first time the code is run it will need to go through the conversion to opcodes, but when the same code is run again a cached version of the opcodes can be used instead of having to convert from high level to low level code.


Because PHP code is interpreted each time the code needs to execute, it means a lot of identical code is recompiled again and again, at least it would be without the ability to cache it.

OPcache is an extension for PHP that saves compiled code into memory so the next time the same code needs to be compiled, PHP can check the cache to see if it’s already there. It checks file sizes and timestamps to determine if the source code has changed and if not, the cache will be used.

You can check to see if OPcache is enabled using phpinfo() or through the command line with php -v. It’s possible your hosting company enables it by default as mine did, but if you have to do it yourself, you can enable OPcache by editing your php.ini file and adding a few lines depending on your specific needs.

I’ll point you to some resources with more information for enabling the cache and for tweaking other settings you might want to change from their default.

Closing Thoughts

The main thing I wanted to get across in this post is that there are additional steps to serve dynamic web pages as opposed to static ones. The dynamic pages first have to be assembled and then converted into the static HTML that gets delivered over the network.

The Zend Engine is likely the interpreter that reads your PHP code, converts it into opcodes that are low level as opposed to the high level abstraction that is PHP.

Instead of converting the code each time it’s called, you can take advantage of OPcache which will store a compiled version of the opcodes that can be used if the original source code hasn’t changed.

Next week I’ll continue talking about PHP and I’ll share some tips for writing more efficient PHP so you can avoid some common bottlenecks that might potentially end up in your code.

« »

Download a free sample from my book, Design Fundamentals.

One comment

  1. I eventually converted my dynamic website to a static one by getting the state of the user and saving/loading a flat file if the user is anonymous (not logged in). I imagine its even faster than Zend but still not bug free.

    Since web servers and databases are so fast nowadays there is no real reason to do it unless you are getting billions of hits on a static page but performance is performance. No use wasting cycles if you do not have to.

Leave a Reply

Your email address will not be published. Required fields are marked *