RSS Webficient

http://www.webficient.com

Last checked about 2 hours ago.

2 people have subscribed to this feed.

Feed frequency

post frequency (last month)

PostRank™ filter

latest 15 posts

« older items




Saturday October 18th, 2008

1.0

Easy Rails Patching

From Webficient, 1 month ago, 0 comments Comment

If you need to extend Rails for whatever reason, here’s a quick tip. Simply add your Ruby code to the config/initializers folder. Since Rails initializers (available since Rails 2 came out) are loaded after Rails framework and plugins, anything executed at this stage will be last. Here’s an example patch which enables “:disable_with” to work with [...]

Thursday October 16th, 2008

1.0

Use Phusion Passenger for Development

From Webficient, 1 month ago, 0 comments Comment

Ruby on Rails is single-threaded, which means that an unusually long request such as a file upload or unruly query will block subsequent requests. This is why one of the most popular production architectures for Rails apps involves a cluster of Mongrel servers behind a reverse proxy such as Nginx. Each Mongrel handles a single [...]

Wednesday October 1st, 2008

5.0

Developer-Specific Environments in Rails

From Webficient, 1 month ago, 0 comments Comment

When you’re working on Ruby on Rails applications in a multiple developer team, you’ll often need to localize certain application settings. You might have your own database credentials, mail server settings, and so on. As a convention, development.rb can be used for settings specific to your development environment. But once this file is added to [...]

Tuesday September 16th, 2008

1.0

Testing IE6 on a Mac

From Webficient, 2 months ago, 0 comments Comment

As of August 2008, Internet Explorer 6 usage still accounts for 30% of the global Web population depending on who you ask. And as all the Web designers in the audience are aware of, making Web sites look good in IE6 can be a bit of a challenge. If you work on a Mac, then a [...]

Monday September 8th, 2008

1.0

Webvanta at Techcrunch50

From Webficient, 2 months ago, 0 comments Comment

Congrats! I’ve had the pleasure of working with Chris and Michael (and their team) on the Webvanta content publishing platform over the last several months. Today, they are unveiling their next generation CMS at the Techcrunch 50.  Webvanta enables Web and graphics designers to easily create full featured Web sites without having to do any programming. You [...]

Saturday September 6th, 2008

5.6

Generate a Google Sitemap in Rails

From Webficient, 2 months ago, 0 comments Comment

A while back, we produced a Capistrano task for automatically crawling your site to pre-cache static content (and find any broken links, exceptions, etc.). We’ve extended the task to also generate a Google Sitemap for use with the Google Webmaster Tools. Our needs were simple: create an XML sitemap without having to add any new controllers, [...]

Thursday August 21st, 2008

1.9

Why Amazon is Good for Craigslist

From Webficient, 3 months ago, 0 comments Comment

I’ve always been a fan of craigslist. I’ve sold tons of furniture, two cars, and even a reptile. I admire Jim Buckmaster, who, incidentally, brought me up to the Bay Area when he hired me as a developer at another startup back in the day. I recently came across a post which claims Craigslist’s fight against [...]

Wednesday August 20th, 2008

1.0

SPF Records and Spam

From Webficient, 3 months ago, 0 comments Comment

Have you ever sent a legitimate email from a corporate email address only to find out from the recipient that it was falsely flagged as spam? You’re at the mercy of someone else’s spam filter, but here’s one solution that can help reduce false positives. SPF Defined The Sender Policy Framework (SPF) was created to reduce spam [...]

Tuesday August 19th, 2008

1.0

Write for Us, Get Exposure

From Webficient, 3 months ago, 0 comments Comment

We’re looking for guest contributors to help cover topics such as Web design, system architecture, and Ruby on Rails programming. There’s no pay involved but we’d love to feature your profile and send you some traffic. If interested, please send a sample of your writing (or link to an existing blog) to blog@webficient.com.

Friday August 8th, 2008

1.0

Valid XHTML for YouTube Videos

From Webficient, 3 months ago, 0 comments Comment

If you ever embed YouTube videos in a Web page, you may not realize it but the embed code is not valid XHTML markup. “Ah come on, why create valid markup in the first place?” you may be thinking. Let’s start with the basics… Why Validate HTML? For an introduction to validating your Web site, see the [...]
1.0

Cross-Browser Transparent Images

From Webficient, 3 months ago, 0 comments Comment

Because of things like rounded corners, shadow effects, and flyout modals, transparent images are very popular in today’s “web 2.0″ design standards. But one of the most annoying problems in building a XHTML/CSS website is the inconsistencies with transparent PNG images. More specifically, the lack of proper support for PNG transparencies in Internet Explorer 6. There [...]
1.0

Third Time’s the Charm

From Webficient, 3 months ago, 0 comments Comment

We relaunched our site today using Wordpress and couldn’t be more ecstatic. We’ve tried on a couple other blogging platforms over the last two years but none seemed to bring the wonderment and awe we’ve experienced with the features and myriad plug-ins available for Wordpress. Our goal was simple: improve the organization of information. We love [...]

Saturday July 12th, 2008

10

Ruby on Rails Gem Dependencies and Plugin Errors

From Webficient, 4 months ago, 0 comments Comment

Rails 2.1 introduced the ability to specify which RubyGems are required by your application, making it much easier to replicate an environment across developer machines and servers. In environment.rb you can list dependencies as follows:

1
2
3
4
5
Rails::Initializer.run do |config|
  config.gem 'haml', :version => '>= 2.0.1' #any version >= to 2.0.1
  config.gem 'pdf-writer', :lib => "pdf/writer" #latest version
  config.gem 'will_paginate', :version => '2.2.2' #identical version
end

However, if you have a plugin dependent on a gem which is not yet installed, you’ll more than likely see something like this when running the new rake gems command.

1
2
rake aborted!
no such file to load -- some_missing_gem

For example, during an upgrade of a Rails 1.x project which uses the Railspdf plugin, a reference to ‘pdf/writer’ led to the aborted rake task.

vendor/plugins/railspdf/lib/railspdf.rb:
1
require 'pdf/writer'

Usually, running a rake task like rake gems initializes all Rails plugins. How do we know this? Adding “—trace” to the end of your rake task will show you the backtrace of everything that’s happening. You’ll notice that the framework calls rails/railties/lib/initializer.rb, responsible for loading plugins. So in this example, while Rails was trying to load the Railspdf plugin, it could not find the required pdf-writer gem.

A quick fix is to update the plugin to check for the presence of the gem:

vendor/plugins/railspdf/lib/railspdf.rb:
1
require 'pdf/writer' if defined? PDF::Writer

(Thanks to Dan Munk for this tip!)

The disclaimer here being that you should make rake gems a required part of your application deployment process. Otherwise, your plugin functionality will fail at runtime if the required gem is missing. Interestingly, Rails does a check for missing gems upon startup but does not prevent Mongrel from running.

Halting Mongrel if Gem Dependencies are Not Met

So what if you do want Mongrel to abort if any dependencies are missing? If your application includes a frozen copy of the Rails framework, you can edit vendor/rails/railties/lib/initializer.rb by adding a call to ‘abort’ method (an alias for Process::abort) to the existing check_gem_dependencies method.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    def check_gem_dependencies
      unloaded_gems = @configuration.gems.reject { |g| g.loaded? }
      if unloaded_gems.size > 0
        @gems_dependencies_loaded = false
        # don't print if the gems rake tasks are being run
        unless $rails_gem_installer
          puts %{These gems that this application depends on are missing:}
          unloaded_gems.each do |gem|
            puts " - #{gem.name}"
          end
          puts %{Run "rake gems:install" to install them.}
+         abort
        end
      else
        @gems_dependencies_loaded = true
      end
    end

If you’d like to take a less intrusive approach (or aren’t including a copy of Rails in the vendor directory), you can monkey patch check_gem_dependencies within your application.

Create a new file in app/config named check_gems.rb and add the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
unless defined?(Rake)
  module Rails
    class Initializer
      alias old_check_gem_dependencies check_gem_dependencies
  
      def check_gem_dependencies
        old_check_gem_dependencies
        unloaded_gems = @configuration.gems.reject { |g| g.loaded? }
        abort if unloaded_gems.size > 0
      end
    end
  end
end

Then, add the following line to environment.rb:

1
require File.join(File.dirname(__FILE__), 'check_gems')

The net result is that if any ‘unloaded’ gems are found, the current Ruby process will end.

For those of you wondering if the above could be added to a Rails initializer, the answer is no. The current version of the Rails Initializer class will not load any application-specific initializers if any gem dependencies are not met.

Additional Rails 2 Resources

The PeepCode Rails 2.1 PDF has good coverage about Gem dependencies and freezing Rails.

Initializers are discussed in Stop Littering In Your Environment File.

Monkeypatching has an entry in the Wikipedia and is covered from a Rails perspective in The Virtues of Monkey Patching.

Thursday July 3rd, 2008

1.0

Phusion Passenger Optimizations

From Webficient, 4 months ago, 0 comments Comment

In a previous article, we installed and tested a baseline configuration of Phusion Passenger, aka mod_rails. In this post, we’ll be comparing memory usage and performance by varying Apache configuration settings in httpd.conf.

Realize that these numbers aren’t absolutes and will vary on your server, depending on its architecture, CPU, and RAM. Our VPS slice has the following specs:

  • Linux Fedora 8, 64-bit
  • 512MB RAM
  • Rails 2.0.2
  • Phusion Passenger 2.0.1
  • Enterprise Ruby 1.8.6 patchlevel 11

We used Apache Bench for testing:

1
# ab -n 10000 -c 100 http://server/app_path

PassengerMaxPoolSize

PassengerMaxPoolSize specifies the maximum number of Ruby on Rails application instances that may be simultaneously active. This setting has a lot of bearing on overall memory consumption and performance.

Memory Usage

1
2
3
4
5
6
PassengerMaxPoolSize    total       used       free     shared    buffers     cached
        1              524460     417040     107420          0      21384     120216
        2              524460     454740      69720          0      22560     127080
        3              524460     489692      34768          0      23160     131860
        4              524460     494548      29912          0      19860     110868
        5              524460     516772       7688          0      19100     103628



Performance

1
2
3
4
5
6
PassengerMaxPoolSize         Requests per second 
        1                    89.09 [#/sec] (mean)
        2                   170.28 [#/sec] (mean)
        3                   224.88 [#/sec] (mean)
        4                   274.94 [#/sec] (mean)
        5                   272.45 [#/sec] (mean)



You’ll notice that our sweet spot is when PassengerMaxPoolSize = 4, since we did not gain any more performance when set to 5, and less memory is used.

PassengerMaxInstancesPerApp

According to the docs, PassengerMaxInstancesPerApp is the maximum number of application instances that may be simultaneously active for a single application. The recommendation is to have the value be less than PassengerMaxPoolSize. Trying different values, ranging from 1 to 3, we observed memory consumption to be a bit less, however the number of requests per second also suffered. We found that setting the value to 0, or no limit, produced the best results performance-wise. If you’re experiencing heavy swapping on a smaller slice, on the other hand, capping this value at something between 0 and PassengerMaxPoolSize will help.

Things that May Affect Benchmarks

If you’re curious about seeing the impact of the above settings on your own configuration, be aware of the following.

Heavy Swapping

As physical memory is used up, your machine will start swapping virtual memory to disk. So be aware of any background processes already running. Disable any cron jobs, scheduled backups, etc.

Linux IP Tables

A software firewall like Linux IP Tables tracks each connection and temporarily persists a handle in a built-in database. It’s entirely possible to overwhelm the system, which will affect your numbers. Your Linux kernel log will show this message: “ip_conntrack: table full, dropping packet.” For an explanation of this issue and how to solve it, see this article.

Wednesday July 2nd, 2008

10

Thin Web Server Benchmarks using Ruby on Rails

From Webficient, 4 months ago, 0 comments Comment

In a previous article, we looked at the performance and memory usage of a Ruby on Rails application running on Passenger Phusion (mod_rails). In this post, we’ll compare the same app running on the Thin Web server behind an Nginx cluster.

Thin Basics

Thin uses the Mongrel parser and Event Machine I/O library. In addition, it uses the Rack interface, allowing you to run other frameworks besides Ruby on Rails.

In a proxying scenario, where Nginx is the “front-end” for the Thin application server, you can leverage Unix domain sockets, which can boost performance and memory usage. Not all HTTP load balancers support it though.

How We Tested

To recap our testing configuration, we’re running a 512MB VPS slice (courtesy of Slicehost.com), and using Apache Bench to load test the login page of our Ruby on Rails blogging platform. This page is not cached but there isn’t a database call either, so our performance numbers don’t include any backend interaction. For other details, refer to the “Benchmark Overview” in our previous post.

Our first test used 4 Unix domain sockets, which are configured as follows, in nginx.conf:

1
2
3
4
5
6
upstream webficient {
  server unix:/tmp/thin.0.sock;
  server unix:/tmp/thin.1.sock;
  server unix:/tmp/thin.2.sock;
  server unix:/tmp/thin.3.sock;
}

Then, Thin was started up using


thin start -s4 --socket /tmp/thin.sock -e production

Results

Memory usage under load using Thin/Nginx appeared better than mod_rails (with Ruby Enterprise Edition).

1
2
             total       used       free     shared    buffers     cached
Mem:        524460     458272      66188          0       7060      82792

Requests per second, on the other hand, were a bit slower than mod_rails (246 RPS vs. 292 RPS with mod_rails) but significantly faster than standard Mongrel.

Dynamic Content Load Test – Thin/Nginx

1
2
3
4
5
6
7
8
9
10
11
Concurrency Level:      100
Time taken for tests:   40.599507 seconds
Complete requests:      10000
Failed requests:        0
Write errors:           0
Total transferred:      30210000 bytes
HTML transferred:       25690000 bytes
Requests per second:    246.31 [#/sec] (mean)
Time per request:       405.995 [ms] (mean)
Time per request:       4.060 [ms] (mean, across all concurrent requests)
Transfer rate:          726.63 [Kbytes/sec] received

Seeing that we had a surplus of available memory during load testing, we tweaked the number of Unix domain sockets to evaluate the effect on overall performance. However, going from 4 to 5 sockets did not improve performance significantly. Dropping down to 3 sockets decreased performance. Therefore, our recommendation for a 512MB VPS slice is 4 sockets. In another test, we doubled Nginx’s number of worker_processes from 3 to 6, however, this did not significantly improve Thin’s numbers either.

Conclusion

While slightly slower than mod_rails, Thin significantly outperforms a vanilla Mongrel Cluster/Nginx configuration. Thus, Thin is a viable solution to those who prefer Nginx to Apache. Recall that previous benchmarks show Nginx is the clear leader in serving up static content. So if your site uses caching extensively, you may want to consider this setup. Otherwise, Phusion Passenger will give you the best bang for the buck.

Another consideration is stability. Thin has been out for quite some time and has had 7 or so releases. Mod_rails is relatively new and not without issues, as seen in its Google group and blog posts. We’ll expect things to improve quickly in this area.

« older items