Foundations of Python Network Programming

(WallPaper) #1
Chapter 8 ■ CaChes and Message Queues

139

Listing 8-1. Using Memcached to Accelerate an Expensive Operation


#!/usr/bin/env python3


Foundations of Python Network Programming, Third Edition


https://github.com/brandon-rhodes/fopnp/blob/m/py3/chapter08/squares.py


Using memcached to cache expensive results.


import memcache, random, time, timeit


def compute_square(mc, n):
value = mc.get('sq:%d' % n)
if value is None:
time.sleep(0.001) # pretend that computing a square is expensive
value = n * n
mc.set('sq:%d' % n, value)
return value


def main():
mc = memcache.Client(['127.0.0.1:11211'])


def make_request():
compute_square(mc, random.randint(0, 5000))


print('Ten successive runs:')
for i in range(1, 11):
print(' %.2fs' % timeit.timeit(make_request, number=2000), end='')
print()


if name == 'main':
main()


Again, the Memcached daemon needs to be running on your machine at port 11211 for this example to succeed.
For the first few hundred requests, of course, the program will run at its usual speed; every time it asks the square of a
particular integer for the first time, it will find it missing from the RAM cache and have to compute it instead. However,
as the program runs and begins to encounter the same integers over and over again, it will start speeding up as it finds
squares that are still present in the cache from the last time it saw a particular integer.
After a few thousand requests drawn from the domain of 5,000 possible input integers, the program should show
a substantial speedup. On my machine, the tenth batch of 2,000 squares runs more than six times faster than the
initial batch.


$ python squares.py
Ten successive runs:
2.87s 2.04s 1.50s 1.18s 0.95s 0.73s 0.64s 0.56s 0.48s 0.45s


This pattern is generally characteristic of caching. The runtime gradually improves as the cache begins to learn
enough keys and values, and then the rate of improvement levels off as Memcached fills and as the percent coverage
of the input domain reaches its maximum.
In a real application, what kind of data might you want to write to the cache?
Many programmers simply cache the lowest level of expensive call, such as queries to a database, reads from the
filesystem, or queries to an external service. At this level, it is often easy to understand which items can be cached for
how long without making information too out-of-date. And if a database row changes, then perhaps the cache can

Free download pdf