views:

108

answers:

2

I've written an application for Google AppEngine, and I'd like to make use of the memcache API to cut down on per-request CPU time. I've profiled the application and found that a large chunk of the CPU time is in template rendering and API calls to the datastore, and after chatting with a co-worker I jumped (perhaps a bit early?) to the conclusion that caching a chunk of a page's rendered HTML would cut down on the CPU time per request significantly. The caching pattern is pretty clean, but the question of where to put this logic of caching and evicting is a bit of a mystery to me.

For example, imagine an application's main page has an Announcements section. This section would need to be re-rendered after:

  • first read for anyone in the account,
  • a new announcement being added, and
  • an old announcement being deleted

Some options of where to put the evict_announcements_section_from_cache() method call:

  • in the Announcement Model's .delete(), and .put() methods
  • in the RequestHandler's .post() method
  • anywhere else?

Then in the RequestHandler's get page, I could potentially call get_announcements_section() which would follow the standard memcache pattern (check cache, add to cache on miss, return value) and pass that HTML down to the template for that chunk of the page.

Is it the typical design pattern to put the cache-evicting logic in the Model, or the Controller/RequestHandler, or somewhere else? Ideally I'd like to avoid having evicting logic with tentacles all over the code.

+1  A: 

I've got just such a decorator up in an open source Github project:

http://github.com/jamslevy/gae%5Fmemoize/tree/master

It's a bit more in-depth, allowing for things like forcing execution of the function (when you want to refresh the cache) or forcing caching locally...these were just things that I needed in my app, so I baked them into my memoize decorator.

jamtoday
+1  A: 

A couple of alternatives to regular eviction:

  1. The obvious one: Don't evict, and set a timer instead. Even a really short one - a few seconds - can cut down on effort a huge amount for a popular app, without users even noticing data may be a few seconds stale.
  2. Instead of evicting, generate the cache key based on criteria that change when the data does. For example, if retrieving the key of the most recent announcement is cheap, you could use that as part of the key of the cached data. When a new announcement is posted, you go looking for a key that doesn't exist, and create a new one as a result.
Nick Johnson