Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

The timestamp-based caching framework: Current data with peak performance

Build a dynamic LRU cache framework using standard Java utility classes

  • Print
  • Feedback

In his timeless masterpiece, The Art of War, Sun Tzu states: "...one who is skilled in warfare principles ...takes the enemy's walled city without attacking... His aim must be to take All-Under-Heaven intact. Therefore, weapons will not be blunted, and gains will be intact."

When we garbage-collect perfectly good objects, we "blunt our weapons" and waste precious system resources by re-creating these objects all over again. By implementing a caching framework, we hope that most of our "gains" resulting from our creation of complex objects will remain "intact." If we store completed objects in the cache, we avoid repeatedly re-creating these objects and thus enjoy a boost in application performance.

Time-to-live, or TTL, caching systems answer the needs of most applications that can afford to use slightly stale data. However, if the objects we cache contain time-sensitive pricing or availability information, they must always remain up to date and cannot be shown to the user as stale. These objects have no reliable time-to-live attribute, and to cache them effectively, we must employ different approaches. One successful approach, a timestamp-based caching framework (TBCF), is presented in this article.

Not caching Britney Spears

Imagine, if you will, a simple Website for selling CDs. On our site, users can search for CDs, check prices, and make purchases. For every user search, our application loads a CD cover picture, item details, price, and user ratings from the database. After all the information is loaded, the application creates CD value objects to massage and store the information from one or more JDBC (Java Database Connectivity) result sets. Then the application renders these CD objects as HTML and delivers the result to the user's browser. After the search results display, our application completes the user's request by allowing the JVM to garbage-collect the complex CD value objects it went to such great lengths to create. The same process then repeats for every other user who executes the same search for the same CD, for example, a Britney Spears CD.

While this typical design approach is straightforward and simple to implement, its performance is often suboptimal. With every user request, CD value objects undergo a "create-use-destroy" cycle, also known as object churning. This cycle does not typically cause problems for small, simple CD objects under low system loads. However, it does cause significant performance degradation if the CD objects are large and complex, requiring several JDBC calls and complex calculations. As the load on the application increases, object-churning problems rapidly intensify. Since objects are not reused, n users will always require the creation of n sets of CD objects and the use of n sets of system resources by our application. This problem is illustrated in Figure 1.

Figure 1. No cache: n users require n sets of objects, causing problems at higher loads

To address the object-churning problem, assembled CD value objects can be stored in a cache. A cache is typically implemented as a map, where CD objects are stored as values, with their IDs as keys. Each CD search request searches the cache first, before querying the database. If an existing CD value object is found in the cache, that object is used; a query to the database to create a new CD object is not required. Thus, with the cache in place, more CD objects are reused, and fewer objects are created and destroyed as part of the churning cycle. In a typical caching mechanism, all the objects that reside in the cache have a time-to-live (TTL) attribute. When the objects stay in the cache longer then their TTL, they become stale. Stale objects are periodically removed from the cache by a background thread (see "Develop a Generic Caching Service to Improve Performance" (JavaWorld, July 2001) for a good implementation of a TTL cache).

  • Print
  • Feedback

Resources