I never thought I would need to worry about caching. Hardware these days is fast. But the more I thought about efficiency the more I realized that my pages don’t change that frequently so why go through the overhead of connecting to a database on every page load? Or for that matter, why load a static file, unserialize something stored, recalculate the ‘year’ in the copyright tag. For that matter, why perform any of these tasks every time the page is loaded when they may change infrequently? Well, luckily Smarty has caching built-in and I found a use for it.
From the Smarty web site:
Here’s where I get happy. I never thought I would need to worry about caching. Hardware these days is fast. But the more I thought about efficiency the more I realized that my pages don’t change that frequently so why go through the overhead of connecting to a database on every page load? Or for that matter, why load a static file, unserialize something stored, recalculate the ‘year’ in the copyright tag. For that matter, why perform any of these tasks every time the page is loaded when they may change infrequently? Well, luckily Smarty has caching built-in and I found a use for it.
From the Smarty web site:
Caching: Smarty provides fine-grained caching features for caching all or parts of a rendered web page, or leaving parts uncached. Programmers can register template functions as cacheable or non-cachable, group cached pages into logical units for easier management, etc.
Wow. Seems like a lot is covered. I can cache the whole page if I want. I can cache the whole page EXCEPT for a dynamic element like a banner ad, or I can register a dynamic function that picks a random Amazon.com book in the midst of an otherwise static page – all while keeping to Smarty’s idea of separating the logic and presentation.
Database queries and caching with Smarty
In a recent project I had to put a full-text search form on a web site. This wasn’t easy because it was searching through HTML files – a mini Google if you will. The trouble was the function that creates the ‘headline’ clip from the page (that highlights the search terms) seemed to be very slow. After asking mailing lists and spending days in the manual I could not get the problem solved. I had a deadline to meet and could not change it.
What I did was implement the current version of the search – problem and all – and used Smarty caching to save load on the system (and save my bottom). Luckily there was an HTML list (links) of popular queries, and a mechanism to record the queries. I used a script to regenerate those queries and use Smarty to cache the results. The only time we had to connect to the DB and perform the query was the first time a search was performed. This was a lifesaver, and it dropped the time to query down to a value that was barely perceptible. Mainly because it rarely had to query the db!
Further Database Queries and Smarty
Another benefit of Smarty caching can be recognized when you have complex queries. We must all work within boundaries. Sometimes you don’t get the chance to select a better DB system, or add hardware. In other words, you work with what you have and find a way to make it better.
I once had to write a page for an e-commerce store that would display the top sellers. Not just top sellers, but three columns of top sellers. There was the top sellers this week, top sellers this month, and top sellers of all time. These changed because of frequent specials and of course, the time spent in the store made a difference in the rank. It was hard to push a product introduced a month ago and put on special this week unless it showed up in the list of top sellers for this week.
But how do you go about that? Performing the SQL queries is easy enough but getting a result back is hard. Really, there is no reason to perform this query 2000 times a day as people drift in and out of the store. The problem is, the store was on a shared host with a dedicated remote database. There was time associated in the connect of course but even more important was the 3 complex queries. Also, they chose a shared host meaning they could not just throw money at the hardware to speed up their queries.
The only problem query in this scenario was the all time best sellers top list. Of course we have no trouble with the others because indices on the right columns make those a snap. But how about sorting through sales records for 6 years and getting a rank for the top sellers? Owch. That can take a long time. Well, a long time from the perspective of a web surfer.
Four seconds to be exact. Can you imagine that? Can you imagine a few people at the same time making that query? That’s the kind of thing that makes machines grind to a halt. You’ll see that type of thing in some of the recent content management systems (CMS) that don’t use any caching. I recently tested one that could only support about 4 users at a time on modest hardware because of their extensive use of, in my opinion, many unnecessary queries.
With Smarty though, this query becomes a non-issue. I ran a script early in the morning that erased the cache for that page and requested it again which regenerated the cache page. You can do this with a simple call to wget or lynx. Problem solved. One query a day is all it took. And because the page showed top sellers for this week and this month there was no need to have it in real time. Even if it was in real time there is no reason to think a sale today would affect sales from the last 6 years in such a dramatic way that it would push an item up the list all the way from the bottom to the top. But even if you wanted the ‘this week’ top sellers list in real time, or a list for the best sellers today, you would just include a dynamic block in Smarty, and only that section would be generated on that page load, the rest of the real hard queries would be cached.
With that in mind, Smarty caching took a script that I wasn’t even able to execute due to the time involved, and turned it into a vital part of the store that helped increase visibility for the top selling items. It also took that 4 second query down to a page load time of 0.4 seconds.
As mentioned above, the shared host used a remote database. That’s a great thing to do actually, but it can kill you on the connect. Of course the connect is what kills you on most databases as long as everything else is up to par.
But why connect to the database at all? If your content is cached you don’t need to, again saving that overhead and speeding up your display that much faster. If you do need to connect to a database to record some statistics or similar, you can do it after the page is sent to the browser by putting your database connect and your subsequent queries in the part of your script AFTER the call to $smarty->display() – meaning the page has already been sent to the browser.
Smarty has a multi-faceted approach to caching. Smarty first takes your template page and caches that as a PHP file. That means it doesn’t have to parse the template on every request. If you choose to use the other caching features, Smarty will then cache the actual output of your page, saving all of the overhead of dynamic files, but allowing you the ability to update the cache whenever you want.
Even if you don’t intend to use caching in any large way it is still a good idea to use Smarty to get acquainted with the idea of an intermediate cache. The Smarty cache will reduce the load on your hardware enabling you to enhance the end-user experience and decrease your dependence on bigger, more expensive hardware. It also allows you to grow your site(s) and traffic without having to worry about hitting the wall and taking the system down during a growth spurt, which can potentially harm revenue. In other words, a Smarty cache let’s you plan for the future. And as you’ve seen in my recent case, Smarty cache can help you get out of a bind when you are dependent on other developers and a timeline.
In short, there simply is no reason not to use a cache. Smarty allows you to implement only as much or as little caching as you like. As a professional PHP or web programmer you need to be efficient as well as effective, and part of being efficient means caching infrequently updated dynamic content.