atomphp/atom — Issue #5: Caching
Author: nerdsrescueme
Created: 2011-10-31 16:18:40+00:00
State: open

## Strategy based cache ##

### Areas of gain ###

* System load
* Latency
* Front facing - User sees faster response time
* Back facing - Application transfers less (IO, DB...)
* Bandwidth
* Front facing - User downloads less content
* Back facing - Application transfers less

#### System Load

System load refers to the actual CPU cycles and other system resources required to perform a script's normal operation. The benefit of using less CPU cycles is that the cycles saved will be available to perform other application operations.

Another prime consideration of system load reduction is memory management. As a script is run PHP does a decent job of garbage collection and clearing your memory, however care must be taken in how you load data into memory to avoid maxing out your allowed memory allocation.

#### Latency

Latency refers to the time it takes for your application's data to travel from point A to point B. Latency can be affected by many different things, some unavoidable. However, it is our job to ensure that we do not put unnecessary strain on the network to allow data to flow freely.

##### Front Facing

Front facing latency is the time it takes for the page or data to be displayed to the user from the time he invoked the desired action. This is arguably the most crucial element in web applications since the entire purpose of building an application is to give the users a pleasant, productive experience.

Many things contribute to front facing latency including the amount of requests made to the server, the size of the data requested and the speed of both the server and the client connection. In addition to these, any time taken in back facing script processing is visible to the user.

##### Back Facing

Back facing latency is time it takes for a request to be processed from start to finish, not including the time it takes to reach the user. Pretty much everything we discuss here will add to back facing latency.

#### Bandwidth

Bandwidth is the amount of data being sent from point A to point B (whether that be within the servers network, or to the user). It is our job to minimize this data for many reasons. First, the application needs to be fast, and the less to download... the faster the application. Second, bandwidth bills can make or break an application, bytes cost money, so we need to make sure that unnecessary bytes do not get sent needlessly.

##### Front Facing

Data sent to the user from the application. This is a crucial element in speeding up an application as sending data both holds up a HTTP process, and costs money for both you and your user. Every care must be taken in ensuring that only necessary bytes are sent to the user, and that those bytes are intended for that user...

##### Back Facing

Data sent back and forth within the application. This can be from the application server to the database. Reading data from an external API, etc. This data must also be minimized wherever possible becuase in most cases it costs money and takes time.

### Invalidation techniques

* By command - Explicit cache expiry required
* By rule - Cache expiry uses rules to invalidate cache

#### Command

Invalidation by command requires very little logic, but very suceptible to delivering invalid data. Very dependent on expiry command being processed when needed.

#### Rule

Invalidation by rule requires more intellignce, but allows minimization of delivering invalid content. Difficult to define a lifetime for a cached object.

### Privacy

Concerns arise for protecting the privacy of cached data. Some data should never be accessible by anyone other than the end user owning the content. Issues arise in caching due to the danger of serving wrong cache object to a certain user, or even somehow allowing global access to cache data repository. Sensitive information should be stored using encryption.

### Available tools

* Web server
* PHP
* File generation
* Database
* Memory
* HTTP Proxy

#### Web Server

Any modern webserver should have the ability to serve static content, bypassing any script execution. Question is, how do we best utilize this significantly faster content delivery to our benefit while still maintaining flexibility in data expiry.

Additionally, how do we best utilize HTTP cache abilities to allow the client machine to handle cache parsing without ever having to touch the server. The main area of concern here would be for asset serving and completely static content.

#### PHP

PHP does not directly create machine code from scripts, an intermediate "script" is created known as optcode. Tools exist to cache this intermediate step in order to speed up PHP processing time by eliminating the need to create a new optcode instance for every script on each request. The main area of concern here would be optimizing PHP itself to allow more request per second, and quicker execution of scripts. The percievable gain is minimal but crucial here as with faster scripts you're able to serve more requests since the server frees up resources faster.

#### File generation

Creating files for cache involves disk IO and (if not used correctly) can create an application bottleneck. However, it does have its uses when compiling complex objects or storing intermediate information that needs to be processed.

#### Database

The database can be a great place to store cached data since it's generally accessible to every application server uniformly, and is relatively fast.

Also, some databases allow you to create temporary in-memory tables to allow for extremely fast read/writes with the power of SQL behind them.

#### Memory

When you have memory to spare, this is arguablly the best option for caching data. Reading data from memory is significantly faster than reading from a database or from disk.

#### HTTP Proxy

Having a smart HTTP proxy can save you hits to your web server. It is worth it to examine the potential gains in caching content outside of your application to be served by another entity. HTTP proxies commonly cache your data using HTTP headers (ETag and Cache-Control) and will serve that data until it is expired. This is somewhat inflexible in that it will not allow you to expire that cache without some hardship. You must be careful with external caches as they create a layer of complexity in your application making it harder to test and debug.

### Considerations

#### Using AJAX within your applicaton

Using AJAX within your application may allow you to cache whole HTML pages while still maintaining the ability to serve dynamic content within the page.

Example: Every page on your site has a "Logged in as: USER" message in the header file, however nothing else on the page changes. This page would be a prime candidate for our fastest caching mechanism HTTP bypassing any script execution, except that it has dynamic content.

For this file we could cache the entire page with a javascript call to another script that returns the name of the user that's logged in. Now we will be able to serve that file from cache for an indefinite amount of time, and still have the page be unique to the visitor. This does require javascript to be enabled, so that needs to be taken into consideration when using this technique.

#### Token based response caching

In some cases you will want to cache a whole page, but have dynamic data automatically inserted into the page based on the request. One solution is to load the cached page and replace a previously placed "cache token" with dynamically created data before sending the response to the user.

When the cache is created a unique cache token would be placed in the cache object, and when the data is requested that token must then be replaced with relavent data... This could be a complex solution, but one that could save system load and back facing latency.

#### Full content caching

In this scenario, a full representation of a page would be created only on the first request. The data would be saved into a path available to the HTTP server to be served directly without PHP ever being invoked.

Special types of content could benefit from this type of content caching, if the page always remains static.

This would also serve as the foundation of AJAX and Token replacement defined above.

#### Partial content caching

Sometimes we simply cannot cache the full page content. However, the script could still benefit from some caching of individual content pieces. In this scenario the script would have to provide a way to cache content as well as retrieve that cache if it exists. I'm not sure of the most graceful way of handling this, but I have never been satisfied with any solution presented to me.

Partial content caching could also be used in conjunction with AJAX caching to provide cached AJAX calls (acting as full content, since they only return data).

#### PHP object caching

PHP objects can be relatively expensive (in system load and memory) to create. For extraordinarily large object (typically database query results) the actual PHP object could be cached to avoid the call made to create it, as well as the actual object creation.

Perhaps PHP object caching of database objects is an integrated part of the framework?