Paging Dr. Cache

Thursday May 22nd, 2008 (permalink)

Photo Credit

When I launched this blog last week I thought it was slow because of my small (256MB) Slice at Slicehost. Then I read about people optimizing their rails installations, so I optimized and it got a bit faster. But, it was still slow. So I read up on optimizing the speed and memory usage of Phusion Passenger aka mod_rails. I made some enhancements and it got a bit better. Problem was, it was still REALLY slow. For a second I got a bit discouraged, I thought to myself “Is this the kind of performance I can expect from a simple rails app?”, I quickly reminded myself that I was probably just not realizing that there was something I could do to make things faster. Then I remembered something I read about caching.

Page Caching is EZ

Following the super-duper-awesome page caching tutorial on the RailsEnvy blog, I quickly setup some caching for my posts controller. I also got my sweepers happening to make sure I’m not serving my guests anything old and stale (bad host indeed).

class PostsController < ApplicationController
...
  caches_page :index, :show
  cache_sweeper :post_sweeper, :only => [:create, :update, :destroy]
...

All together it took about 15 minutes, I spent some extra time troubleshooting a problem that was the result of naming my sweeper PostSweeper.rb rather than post_sweeper.rb.

mod_rails configuration

In the RailsEnvy tutorial they mention setting up some custom mod_rewrite rules to handle telling Apache to serve your cached pages instead of passing the requests on to your mongrel instance. From what I read in the Passenger/mod_rails user guide, this wasn’t necessary, plus they mention that mod_rails doesn’t play well with mod_rewrite anyhow, so I didn’t change anything about my vhost config.

PLS 2 BEE BENCHMRKIN

I read all about how cool and fast page caching was and not that I didn’t believe it, but I was curious how cool and fast it really was. To test any performance improvements I used Apache Benchmark (ab for short).

The test consisted of running 500 requests with a concurrency level of 5

$> ab -c 5 -n 500 http://www.lengelzigich.com/

I ran this three times from start to finish, waiting about 30 seconds between each run. Then I ran it a fourth time and saved those results.

Before Page Caching

Server Software:        Apache
Server Hostname:        www.lengelzigich.com
Server Port:            80

Document Path:          /
Document Length:        4599 bytes

Concurrency Level:      5
Time taken for tests:   92.220691 seconds
Complete requests:      500
Failed requests:        2
   (Connect: 2, Length: 0, Exceptions: 0)
Write errors:           0
Total transferred:      2552000 bytes
HTML transferred:       2299500 bytes
Requests per second:    5.42 [#/sec] (mean)
Time per request:       922.207 [ms] (mean)
Time per request:       184.441 [ms] (mean, across all concurrent requests)
Transfer rate:          27.02 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:       74  392 2023.8     78   19114
Processing:    96  115  34.8    103     536
Waiting:       94  111  24.8    100     207
Total:        172  508 2022.9    183   19215

Percentage of the requests served within a certain time (ms)
  50%    183
  66%    187
  75%    199
  80%    223
  90%    249
  95%    276
  98%   7114
  99%  11201
 100%  19215 (longest request)

After Page Caching

Server Software:        Apache
Server Hostname:        www.lengelzigich.com
Server Port:            80

Document Path:          /
Document Length:        4602 bytes

Concurrency Level:      5
Time taken for tests:   24.150369 seconds
Complete requests:      500
Failed requests:        0
Write errors:           0
Total transferred:      2553500 bytes
HTML transferred:       2301000 bytes
Requests per second:    20.70 [#/sec] (mean)
Time per request:       241.504 [ms] (mean)
Time per request:       48.301 [ms] (mean, across all concurrent requests)
Transfer rate:          103.23 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:       74   88 180.5     78    4008
Processing:    95  119  36.3    105     494
Waiting:       93  116  35.4    103     492
Total:        171  208 183.2    186    4109

Percentage of the requests served within a certain time (ms)
  50%    186
  66%    192
  75%    202
  80%    218
  90%    247
  95%    261
  98%    277
  99%    392
 100%   4109 (longest request)

The Results

  • 4x improvement in requests per second
  • Time per request reduced by 75%
  • 100% of requests were served in 4 seconds or less compared to 15 seconds or less

Overall I’m more than pleased with the results and plan on taking a look at the next RailsEnvy tutorial on ActionCaching.

Posted In: Ruby on Rails

Leave a Response

 (required)
 (required, never shared)

 (required)

(required)

Let's Chat

E-Mail Me

Categories

Recent Posts

Subscribe

RSS Icon