2009
11/13
16:09

Faster alternatives to ActiveRecord::Base.to_xml (Rails Performance Series)

This is part 5 of my ongoing series on Ruby on Rails performance. Today’s topic is a bit more complicated that some of the previous parts.

I’m going to explore an alternative to using the method ActiveRecord::Base.to_xml.

Before I get into that, I probably should explain why. After all, ActiveRecord::Base.to_xml is really easy to use. The alternative I’m going to demonstrate isn’t very easy to use.

The problem is that ActiveRecord::Base.to_xml can be really slow—even after making the optimizations I’ve explored in the previous parts to this series. For fairly simple AR objects, this won’t be a problem. However, when you have a deep object hierarchy and need substantial portions of it to be included in the XML response, it becomes a problem.

One instance where I encountered this was a nested has_many tree. That is, the object tree looks something like this:

ParentObject has_many ChildObjects
Each ChildObject has_many OtherObjects

The XML output is often 100k or more, and representing a few dozen or more total objects.

Read more...

10/26
19:14

Measuring ActiveResource Response Times (Rails Performance Series)

This is a quick one, but if your Rails app uses ActiveResource as a client, it can be really useful to know something about each ARes request.

ActiveResource actually has some built-in logging of what requests are made, the response size, and how long it took. But, it’s not enabled. The good news is, it’s easy to turn it on.

I like to make ActiveResource’s logging match the rest of my environment — that is, it will log when in development mode and not in production mode.

Add the following to a file in config/initializers/:

ActiveResource::Base.logger = ActionController::Base.logger

Obviously, if you want it to go to a different log file, or function at a different log level, you can create a new Logger instance instead.

The logging output will look something like this:

GET http://api-server.com/resources.xml
--> 200 OK (1526 69ms)
10/21
15:08

Rails XML Parsing (Rails Performance Series)

In part 3 of my Ruby on Rails Performance Series we’ll look at how to improve the parsing speed of XML content.

Rails will automatically parse XML in two key places:

1. When XML content is sent to a controller/action pair via POST or PUT. (Your app is an API server.)
2. When XML content is received from an ActiveResource request. (Your app is an API client.)

The default XML parser is REXML. It’s written in pure Ruby which makes it very portable. And slow. Very slow.

So, we need to replace REXML with something faster. The key is the libxml-ruby gem which is just a binding to the very fast libxml2 C library.

libxml-ruby has a different set of methods from REXML and is not drop in compatible. If you’re planning on moving your own REXML parsing code to libxml-ruby, it will take some work. However, it’s worth it. In one particular project, I had about a 100x speed improvement!

Rails, as it often does, makes the switch to libxml-ruby super easy. First, install the gem (requires a functioning compiler, the libxml2 library, and headers for libxml2):

gem install libxml-ruby

Then, just add a new file to config/initializers/. Let’s call it config/initializers/xml_config.rb. In that file, put this:

ActiveSupport::XmlMini.backend = 'LibXML'

This was only added in recent versions of Rails, I believe in 2.3.

Restart your Rails app server(s) and off you go!

10/14
15:51

Ruby XML Generation (Rails Performance Series)

The standard way to build XML in Ruby is with the Builder gem.

Builder iterates over each character in the output text to determine if it needs to escape it. When generating larger XML documents, this can be quite slow.

Thankfully, the solution is already available via the fast_xs gem. This gem does compile an extension, so you’ll need a working compiler.

gem install fast_xs

Then just require it after Builder:

require 'builder'
require 'fast_xs'

It will be used automatically by Builder going forward.

If your app is built on Rails, it’s even easier. Just install the gem—that’s it! Recent versions of Rails will auto-detect the existence of fast_xs and enable it.

10/07
17:32

Ruby on Rails Performance Series: Intro and all about YAML

Lately I’ve been doing a lot of API type work in Rails — both client and server. It mostly uses Rails’ default XML generation and consumption.

Along the way I’ve discovered that the default performance of XML and related things on Ruby and Rails is, shall we say, less than amazing. On the bright side, there are a number of ways to improve matters.

So, I’m going to do a series on improving the performance of Rails’ API-related stack.

I’ll start off with serialized columns in ActiveRecord.

Read more...

06/26
02:34

Disabling Rails asset timestamps

One of the common questions in Rails land is how to disable the funny numbers at the end of images and CSS stylesheets. Let’s explore what exactly those numbers are, why they’re sometimes helpful, and how to turn them off when they’re not.

Read more...

04/23
02:59

Rails 2.3 compatible version of limited_sessions is ready

Rails 2.3 made a lot of changes in how requests are handled. Most (all?) of this has to do with its new support for Rack. Anyway, all of these changes left Rails 2.3 incompatible with the last version of the Limited Sessions plugin.

So, here’s a shiny new version of Limited Sessions to go with your shiny new version of Rails.

Read more...

2008
08/16
03:57

Rails 500 error - IP spoofing attack

Apparently Rails 2.1 has the nifty ability to throw a 500 Internal Server Error with the message “IP spoofing attack?!” under certain circumstances.

Unfortunately, those circumstances include a common Apache/Mongrel deployment and Yahoo’s crawler, Slurp, trying to index your site. It’s possible Apache/Mongrel isn’t required; I’m unsure.

The key is that Slurp includes both a Client-IP header (HTTP_CLIENT_IP by the time it hits Rails) and an X-Forwarded-For header (HTTP_X_FORWARDED_FOR). When both are present, Rails assumes something evil is happening and voluntarily dies. Neat.

Such a header can be relied on only if it was set by a trusted proxy. Otherwise, it’s hard to know if it was spoofed. The difficulty is for Rails to know which one, if any, was set by a trusted proxy.

I deploy Rails in a common Apache w/mod_proxy_balancer and Mongrel setup. Apache uses X-Forwarded-For natively, so that’s the one I want to trust. To make Rails happy, I’ve just told Apache to delete the Client-IP header if present.

Adding RequestHeader unset Client-IP to the virtual host configuration seems to do the trick.

This does require mod_headers to be enabled in Apache.

07/24
17:14

Rails plugin Limited Sessions updated

I updated my limited_sessions plugin to improve support for Rails 2.1. It should maintain backwards compatibility.

The change surrounds Rails 2.1’s new partial updates support. Basically, it’s turned off for sessions so the session is kept current and doesn’t expire if the user is active.

limited sessions

2007
11/16
22:56

active_scaffold overrides

the active_scaffold plugin for rails can be useful at times. as is typical of a large library, when it doesn’t do quite what you want, you have to start overriding parts of it.

unfortunately, there aren’t a lot of documented options to doing this with active_scaffold—at least not in the published docs. the code comments discuss more available options. so, what follows is an attempt to document some of those options.

Read more...

Page: 1 2