264 Posts tagged with rails
Where's the bloat: Tracking 'require' memory usage in Ruby and Rails
Among the other awesome things that Ruby Enterprise Edition’s inclusion of the RailsBench GC patch provides is the addition of the allocated_size method on Ruby’s GC constant.
Eric Lindvall recently devised a very clever use for this GC.allocated_size method:
If I wanted to see what was contributing to the large memory footprint of an application on startup, tracking how much memory was allocated during each
requirewould give me a good place to start.
Given the size of GC.allocated_size before and after require calls, we can determine the initial memory profile of any ruby gem, library, file, or Rails model.
To use this to determine the initial memory profile of a beefy Rails application, you’ll first want to download his require_tracking hax. Then, load your production Rails application’s environment with require_tracking turned on:
RAILS_ENV=production ruby -r/tmp/require_tracking.rb -e "require 'config/environment'"
Memory used by file:
File KB
------------- --------
config/environment: 209,623
/srv/myapp/releases/20091230003757/app/models/user: 73,653
/srv/myapp/releases/20091230003757/app/models/store: 70,962
./config/boot: 15,021
/srv/myapp/releases/20091230003757/app/models/discount_code: 9,813
/srv/myapp/releases/20091230003757/app/models/order: 9,390
./config/../vendor/rails/railties/lib/initializer: 9,348
...
71.9 M used by the User model? Holy wow! I know what I’ll be doing today….
Spinning up a new Rails app « Katz Got Your Tongue?
Running Rails performance tests on real data
Railscasts - Delayed Job
Ruby at ThoughtWorks
railsmachine's moonshine at master - GitHub
Ryan's Scraps: What's New in Edge Rails: Nested Object Forms
The technical story of Muxtape
Rails Metal: a micro-framework with the power of Rails: \m/
Updates:
- Clarified the distinction between Rails Metal and Rack middleware after more information from @Josh in the comments. Thanks!
- Read more about metal from DHH on the Official Rails Blog.
- Demonstrate Testing Metal end points
- Update Poller example to match new style
- Cover Sinatra Integration
- Correct benchmarks
Josh Peek committed a new feature to Edge Rails today: Rails Metal. After the recent work to replace Rails’ crufty request processing code with Rack and integrate its middleware support, Rails Metal is a logical progression that allows Rails apps to use the power of Rack middleware to create super-fast actions.
For example, here’s a sample “Hello World” Metal:
class Poller < Rails::Rack::Metal
def call(env)
if env["PATH_INFO"] =~ /^\/poller/
[200, {"Content-Type" => "text/html"}, "Hello, World!"]
else
[404, {"Content-Type" => "text/html"}, "Not Found"]
end
end
endAnd for comparison, a “Hello World” controller:
class OldPollerController < ApplicationController
def poller
render :text => "Hello World!"
end
endSo, let’s fire up ruby script/server and see what this gives us:
# traditional Controller
$ curl 127.0.0.1:3000/old_poller/poller
Hello World!
# the new Metal
$ curl 127.0.0.1:3000/poller
Hello World!So, the point of all of these other “micro-frameworks” is that they’re faster than Rails, right? Let’s benchmark this new “Hello World” Metal:
# first, let's benchmark the traditional controller
$ ab -n 1000 http://127.0.0.1:3000/old_poller/poller
... snip ...
Requests per second: 408.45 [#/sec] (mean)
Time per request: 2.448 [ms] (mean)
# now for the Metal middleware
$ ab -n 1000 http://127.0.0.1:3000/poller
... snip ...
Requests per second: 1154.66 [#/sec] (mean)
Time per request: 0.866 [ms] (mean)For this trivial “Hello World” benchmark, Rails Metal is 2.8x faster than a Controller. Awesome. Have a couple actions of your app you need to optimize? Instead of breaking them out into a separate application using a micro-framework, add a Metal inside your existing app. You get the performance benefits of processing requests outside of ActionPack, and it’s all integrated as a part of your Rails app. Easy!
Sinatra Metal
You can now also use Sinatra to create Metal end points:
Sinatra::Application.default_options.merge!(:run => false, :env =>
:production)
Api = Sinatra.application unless defined? Api
get '/interesting/new/ideas' do
'Hello Sinatra!'
endFirst person to show the use of a Merb app as a Metal end point wins a prize.
Standalone Execution
Additionaly, Rails Metal are able to be executed in a separate process from your Rails application using rackup:
rackup -s mongrel app/metal/poller.rbThis runs the Poller Metal separeately from Rails, on it’s own port (rackup defaults to 9292). This is perfect if you have an action that’s taking a very long time (for example a file upload) that you’d like to split out from the normal Rails request processing queue.
Testing Metal
Update: After several people commented asking how to test metal, DHH chimed in and recommend Integration Testing for Metal end points, as they hit the whole stack, and I submitted a patch cleaning up the Integration Testing behavior of Metal. Testing Metal end points now works just like any other Integration test:
class PollerTest < ActionController::IntegrationTest
test "poller returns hello world" do
get "/poller"
assert_response 200
assert_response :success
assert_response :ok
assert_equal "Hello World!", response.body
end
endFun With Middleware
So, essentially, Rails Metal is a thin wrapper around Rails’ new Rack middleware support. Rack middleware is pretty powerful stuff: framework-independent components that process requests independently or in concert with other middleware. For example, here’s a simple piece of Rack middleware that runs a regex on responses:
class RegexMiddleware
def initialize(app)
@app = app
end
def call(env)
status, headers, response = @app.call(env)
new_response = []
response.each do |part|
new_response << part.gsub(/World/, 'Middleware')
end
[status, headers, new_response]
end
endTo use this rack middleware in Rails, add this line to your environment.rb
Rails::Initializer.run do |config|
...
config.middleware.use RegexMiddleware
end Restart your server, and check out what happens:
$ curl 127.0.0.1:3000/poller
Hello Middleware!The Rack middleware filtered the output of the Metal we created before. This works with output generated by normal controllers and everything too. The possible uses of this pattern are endless:
- Single Sign On
- Request/Response Signing (think OAuth)
- Asset Compression
rack-contrib is a nice collection of Rack middleware if you’re interested in more examples.
Rails Metal is a simple wrapper around the existing (yet undocumented) Rack middleware support in Edge Rails that attempts to DRY the process of using middleware to create endpoints (like a poller) as opposed to filters (which are better implemented as traditional middleware, like the examples above). For example, Rails Metal might be used:
- To speed up a ‘poller’ action called by all active users of a popular web-based chat application every 3 seconds (hint: Campfire).
- To improve the performance of any API endpoint
- To process file uploads outside of the Rails request queue
- To authorize delivery of cached content
We don’t need no stinking micro-frameworks
With the additional of Metal and Rack middleware support, Rails effectively includes a micro-framework of its own; one that either tighly integrates with Rails or is executed separately – whichever the need dictates.
This is a great response by the Rails team to all of the buzz surrouding micro-frameworks: a micro-framework with the power of Rails. I’m definitely going to try this approach to squeeze a couple extra requests per second out of a heavily trafficked API call – let me know in the comments if you find a use for it.
Read up a bit more on Rack and then take a look at Josh’s commit Introducing Rails Metal (and the ensuing comments) if you’re interested for more information.
bong
jnunemaker's user_stamp
Panda - Open source video platform
Another comparison of HAProxy and Nginx « Affection Code
The Rubyist
A Thinking Man's Sphinx
Thinking Sphinx
Redesign your site in place using Rails custom mime types
The Rails Documentation App - Rails-doc.org
A List Apart: Issue 257 - The why and how of Ruby on Rails
Edge Rails gets Declarative Gem Dependencies
What's New in Edge Rails: Has Finder Functionality
NestedHasManyThrough
Paperclip
rails_environments
assert_valid_markup
Fire Eagle - Easily share your location online! Personalise lots of sites and services!
NginxHttpUpstreamFairModule
Is edge Rails broken?
The NullDB Connection Adapter Plugin
db-populate
Simple Ruby SMTP Server / ActiveRecord Importer
Process title support for Mongrel
Fixing attachment_fu on Edge Rails
When, a Rails plugin
starling and asynchrous tasks in ruby on rails
SwitchPipe - Process Manager and Proxy for Rapid Web App Deployment
Dr Nic » Get ready for the TextMate “Trundle to Rails 2.0 Bundle”
YAWS (Erlang) frontend for rails apps
SoftValidations
friendly_id
Spreedly
query-reviewer
sudo gem install starling
Desert
simply_versioned
skynet
Minimal Cart..
The Rails Way (Book Review)
spawn
Rails Edge Change: How to add a counter cache to an existing db table
What's New in Edge Rails: Pluggable Controller Caching
Microformat helper for Ruby on Rails
DeHorrible: RESTifying SimpleDB
Interlock
Beanstalkd
Display Validation Errors For Your Ajaxified Form
Streamlined - Trac
Panasonic Youth – MultiRails 0.0.3 released
Setting up a new Rails app with Git
[ANN] Giston; Piston lookalike for Git
err.the_blog.find_by_title('Evil Twin Plugin')
CarryOn
Masochism
MultiRails
sliding_session_timeout
Cache-Control Header for Amazon S3
Mongrel Cluster and Monit - pmade inc.
Almost Painless Nested Resources
MultiAppRouting
deciphering objects.log
identity-matcher - Google Code
redirect_routing
QuarkRuby: Ruby on Rails Security Guide
resource_this - DRY Rails Resource Controllers
I’ve always been annoyed at the lack of maintainability that comes with using multiple resource controllers in my Rails apps. Each generated resource controller clocks in at 85 lines, and most of mine only differ from each other by a line or two – an added before_filter or a change in the url that the users is redirected to after the creation of a new Widget. Not very DRY. When coming back to each one of these controllers to add or adjust features, it takes me entirely too much time to sift through the stock 85 lines and find my application-specific behavior.
Enter resource_this
git clone git://github.com/jnewland/resource_this.gitresource_this aims to solve this maintainability problem by making your stock resource controllers look like this:
class PostsController < ActionController::Base
resource_this
endBehind the scenes, this code is generated:
class PostsController < ActionController::Base
before_filter :load_post, :only => [ :show, :edit, :update, :destroy ]
before_filter :load_posts, :only => [ :index ]
before_filter :new_post, :only => [ :new ]
before_filter :create_post, :only => [ :create ]
before_filter :update_post, :only => [ :update ]
before_filter :destroy_post, :only => [ :destroy ]
protected
def load_post
@post = Post.find(params[:id])
end
def new_post
@post = Post.new
end
def create_post
@post = Post.new(params[:post])
@created = @post.save
end
def update_post
@updated = @post.update_attributes(params[:post])
end
def destroy_post
@post = @post.destroy
end
def load_posts
@posts = Post.find(:all)
end
public
def index
respond_to do |format|
format.html
format.xml { render :xml => @posts }
format.js
end
end
def show
respond_to do |format|
format.html
format.xml { render :xml => @post }
format.js
end
end
def new
respond_to do |format|
format.html { render :action => :edit }
format.xml { render :xml => @post }
format.js
end
end
def create
respond_to do |format|
if @created
flash[:notice] = 'Post was successfully created.'
format.html { redirect_to @post }
format.xml { render :xml => @post, :status => :created, :location => @post }
format.js
else
format.html { render :action => :new }
format.xml { render :xml => @post.errors, :status => :unprocessable_entity }
format.js
end
end
end
def edit
respond_to do |format|
format.html
format.js
end
end
def update
respond_to do |format|
if @updated
flash[:notice] = 'Post was successfully updated.'
format.html { redirect_to @post }
format.xml { head :ok }
format.js
else
format.html { render :action => :edit }
format.xml { render :xml => @post.errors, :status => :unprocessable_entity }
format.js
end
end
end
def destroy
respond_to do |format|
format.html { redirect_to :action => posts_url }
format.xml { head :ok }
format.js
end
end
endNested resources like so:
class CommentsController < ActionController::Base
resource_this :nested => [:posts]
endThis generates a very similar controller to the one above with adjusted redirects and one additional before_filter / loader method pair to grab the parent resource. In this case:
before_filter :load_post
def load_post
@post = Post.find(params[:post_id])
endThe separation of logic – DB operations in before_filters, rendering in the standard resource controller methods – makes this approach ridiculously easy to customize. Need to load an additional object for the :show action? Slap another before_filter on it. Need to change the path that the :update action redirects to? Override the :update action with your new rendering behavior. And this customized behavior sticks out like a sore thumb – making it infinitely easier to maintain.
Oh, there’s also a generator:
./script/generate resource_this FooKlass [title:string body:text]This works just like the resource generator, with the addition of the resource_this line to your controller and a functional test. No views are generated, so the test focuses on the XML behavior of this controller.
Contributing
resource_this is hosted on GitHub, so feel free to fork it and send a pull request with your changes.
resource_this
monkeycharger
Ambition - SQL generation using Ruby's Enumerable class
Rails Chatter » Blog Archive » Ruby on Rails: Using Nested Resources with Polymorphic Associations
Synaphy · Seesaw - High-Availability Mongrel Packs
err.the_blog.find_by_title('Be Dee Dee and Me')
Secure UTF-8 Input in Rails - igvita.com
growing up your acts_as_taggable :: snax
Portable Social Networks at Mashup Camp :: UltraNormal
Noobkit Docs, Ruby on Rails API documentation... on Rails.
CachableFlash
MileMarker
Pivotal Blabs : Access Control & Permissions in Rails
Warehouse — Subversion Browser
Jake@Nitobi » Blog Archive » RobotReplay and Rails on Amazon EC2
code_fu - AJAX file uploads in Rails using attachment_fu and responds_to_parent
RubyWorks production stack - from ThoughtWorks
RailsConf '07 Roundup
David Heinemeier Hansson, by James Duncan Davidson. Creative Commons BY-NC-ND
I spent the past several days in Portland, OR, for RailsConf, the yearly gathering of the vibrant Ruby on Rails community. O’Reilly Media and Ruby Central put on an incredible conference. My only disappointment was that I couldn’t attend all of the presentations. Luckily, most of the presentation slides are online (some with accompanying code!!):
But by far, the most valuable part of the whole event was the time I spent in the hallways and around Portland with other Rails developers. In the two years I’ve been working with Rails, I’ve networked and collaborated with dozens if not hundreds of Rails developers online. It was great to finally be able to associate faces and voices with their respective names, blogs, and chat handles.
I also wrangled Erik Kastner and Charles Brian Quinn into the Capazon project while in Portland – look for some updates on that front in the near future.
A special thanks to the following folks for making my RailsConf an especially great time:
