Performance Boost from memcached

January 22, 2009

The server that I am currently hosting this site on is not a very powerful box, which is why I have been putting a lot of effort into getting things configured on it as efficiently as possible. One of the things that I am using to achieve quick response times is memcached. I ran some tests on the server before installing memcached.

** SIEGE 2.67
** Preparing 1 concurrent users for battle.
The server is now under siege...

Lifting the server siege...      done.                                         
Transactions:                      16 hits
Availability:                 100.00 %
Elapsed time:                  10.95 secs
Data transferred:               0.14 MB
Response time:                  0.26 secs
Transaction rate:               1.46 trans/sec
Throughput:                     0.01 MB/sec
Concurrency:                    0.38
Successful transactions:          16
Failed transactions:               0
Longest transaction:            1.67
Shortest transaction:           0.04

** SIEGE 2.67
** Preparing 5 concurrent users for battle.
The server is now under siege...

Lifting the server siege...      done.                                         
Transactions:                     102 hits
Availability:                 100.00 %
Elapsed time:                  11.48 secs
Data transferred:               0.91 MB
Response time:                  0.15 secs
Transaction rate:               8.89 trans/sec
Throughput:                     0.08 MB/sec
Concurrency:                    1.29
Successful transactions:         102
Failed transactions:               0
Longest transaction:            3.10
Shortest transaction:           0.00

These results are not very fast. For a single connection, the server was only able to process 16 requests in 10 seconds. I am now using memcached to cache both my views and my database queries. This means that if someone is trying to access a page that is currently in the cache, Python has to do almost no work to render it. Here are the results:

** SIEGE 2.67
** Preparing 1 concurrent users for battle.
The server is now under siege...

Lifting the server siege...      done.                                         

Transactions:                    1376 hits
Availability:                 100.00 %
Elapsed time:                   9.43 secs
Data transferred:              12.26 MB
Response time:                  0.01 secs
Transaction rate:             145.92 trans/sec
Throughput:                     1.30 MB/sec
Concurrency:                    0.99
Successful transactions:        1376
Failed transactions:               0
Longest transaction:            0.07
Shortest transaction:           0.00

** SIEGE 2.67
** Preparing 5 concurrent users for battle.
The server is now under siege...

Lifting the server siege...      done.                                             
Transactions:                    1647 hits
Availability:                 100.00 %
Elapsed time:                  11.17 secs
Data transferred:              14.68 MB
Response time:                  0.02 secs
Transaction rate:             147.45 trans/sec
Throughput:                     1.31 MB/sec
Concurrency:                    2.94
Successful transactions:        1647
Failed transactions:               0
Longest transaction:            6.94
Shortest transaction:           0.00

Now, a single concurrent connection is able to serve 1697 requests in roughly the same amount of time. I went from 1.46 transactions per second up to 145.92 transactions each second. That is very nearly a 100 fold increase in performance.

It looks like memcached is a huge benefit. If you are not familiar with it, it is basically an in memory hash table. It runs as a daemon and accepts requests to get and set values over a TCP socket. Because everything happens in memory, memcached never blocks for disk reads, so responses are always quick. As I said, it is currently caching both my views and my database queries.

For example, when a request comes in for the url "/blog", Python checks the memcache for a copy of the html for that view. If it exists, Python returns the data. It works essentially the same way for database queries. The main trade off of using memcache is that it removes some of the ACID compliance from your database because it could be possible to retrieve stale data. This generally isn't a big deal on simple web site, especially if the cache timeout is relatively small.

Check out my other pages tagged "blog".