Rails and Merb Merge: Performance (Part 2 of 6) »

Created at: 29.12.2009 23:45, source: Engine Yard Blog, tagged: Technology merb Rails 3 Rails Performance

The next significant improvement that we hoped to bring to Rails from Merb was faster performance. Because Merb came after Rails, we had the luxury of knowing which parts of Rails were used most often and optimizing performance for those parts.

For Rails 3, we wanted to take the performance optimizations in Merb and bring them over to Rails. In this post, I’ll talk about just a few of the performance optimizations we’ve added to Rails 3: reducing general controller overhead and (greatly) speeding up rendering a collection of partials.

For our initial performance work, we focused on a few specific but commonly used parts of Rails:


  • General overhead (the router plus the cost of getting in and out of a controller)

  • render :text

  • render :template

  • render :partial

  • rendering a number (10 and 100) of the same partials in a loop

  • rendering a number (10 and 100) of the same partials via the collection feature


This was definitely a limited evaluation, but it covered most of the cases where performance might be at a premium and the Rails developer was unable to do anything about it.

General Controller Overhead


The first thing was improving the general overhead of a Rails controller. Rails 2.3 doesn’t have any way to test this, because you’re forced to use render :string to send back text to the client, which implicates the render pipeline. Still, we wanted to reduce it as much as possible.

When doing this work, we used Stefan Kaes’ fork of ruby-prof that comes with the CallStackPrinter (the best way I’ve ever seen to visualize profile data from a Ruby application.) We also wrote a number of benchmarks that could double as profile runs if I wanted to zero in and get more precise data.

When we looked at overhead, it was dominated by setting the response. Digging a bit deeper, it turned out that ActionController was setting headers directly, which then needed to be re-parsed before returning the response to get additional information. A good example of this phenomenon was in the Content-Type header, which had two components (the content-type itself and an optional charset). The two components were available on the Response object as getters and setters:

def content_type=(mime_type)
  self.headers["Content-Type"] =
    if mime_type =~ /charset/ || (c = charset).nil?
      mime_type.to_s
    else
      "#{mime_type}; charset=#{c}"
    end
end
 
# Returns the response's content MIME type, or nil if content type has been set.
def content_type
  content_type = String(headers["Content-Type"] || headers["type"]).split(";")[0]
  content_type.blank? ? nil : content_type
end
 
# Set the charset of the Content-Type header. Set to nil to remove it.
# If no content type is set, it defaults to HTML.
def charset=(charset)
  headers["Content-Type"] =
    if charset
      "#{content_type || Mime::HTML}; charset=#{charset}"
    else
      content_type || Mime::HTML.to_s
    end
end
 
def charset
  charset = String(headers["Content-Type"] || headers["type"]).split(";")[1]
  charset.blank? ? nil : charset.strip.split("=")[1]
end



As you can see, the Response object was working directly against the Content-Type header, and parsing out the part of the header as needed. This was especially problematic because as part of preparing the response to be sent back to the client, the Response did additional work on the headers:

def assign_default_content_type_and_charset!
  self.content_type ||= Mime::HTML
  self.charset ||= default_charset unless sending_file?
end



So before sending the response, Rails was once again splitting the Content-Type header over semicolon, and then doing some more String work to put it back together again. And of course, Response#content_type= was used in other parts of Rails, so that it was correctly set based on the template type or via respond_to blocks.

This was not costing hundreds of milliseconds per request, but in applications that are extremely cache-heavy, the overhead cost could be larger than the cost of pulling something out of cache and returning it to the client.

The solution in this case was to store the content type and charset in instance variables in the response, and merge them in a quick, simple operation when preparing the response.

attr_accessor :charset, :content_type
 
def assign_default_content_type_and_charset!
  return if headers[CONTENT_TYPE].present?
 
  @content_type ||= Mime::HTML
  @charset      ||= self.class.default_charset
 
  type = @content_type.to_s.dup
  type < < "; charset=#{@charset}" unless @sending_file
 
  headers[CONTENT_TYPE] = type
end



So now, we’re just looking up instance variables and creating a single String. A number of changes along these lines got overhead down from about 400usec to 100usec. Again, not a huge amount of time, but it could really add up in performance-sensitive applications.

Render Collections of Partials


Rendering collections of partials presented another good opportunity for optimization. And this time, the improvement ranked in milliseconds not microseconds!

First, here was the Rails 2.3 implementation:


def render_partial_collection(options = {}) #:nodoc:
  return nil if options[:collection].blank?
 
  partial = options[:partial]
  spacer = options[:spacer_template] ? render(:partial => options[:spacer_template]) : ''
  local_assigns = options[:locals] ? options[:locals].clone : {}
  as = options[:as]
 
  index = 0
  options[:collection].map do |object|
    _partial_path ||= partial ||
      ActionController::RecordIdentifier.partial_path(object, controller.class.controller_path)
    template = _pick_partial_template(_partial_path)
    local_assigns[template.counter_name] = index
    result = template.render_partial(self, object, local_assigns.dup, as)
    index += 1
    result
  end.join(spacer).html_safe!
end



The important part here is what happened inside the loop, which could occur hundreds of times in a large collection of partials. Here, Merb had a higher performance implementation which we were able to bring over to Rails. This is the Merb implementation.

with = [opts.delete(:with)].flatten
as = (opts.delete(:as) || template.match(%r[(?:.*/)?_([^\./]*)])[1]).to_sym
 
# Ensure that as is in the locals hash even if it isn't passed in here
# so that it's included in the preamble.
locals = opts.merge(:collection_index => -1, :collection_size => with.size, as => opts[as])
template_method, template_location = _template_for(
  template,
  opts.delete(:format) || content_type,
  kontroller,
  template_path,
  locals.keys)
 
# this handles an edge-case where the name of the partial is _foo.* and your opts
# have :foo as a key.
named_local = opts.key?(as)
 
sent_template = with.map do |temp|
  locals[as] = temp unless named_local
 
  if template_method && self.respond_to?(template_method)
    locals[:collection_index] += 1
    send(template_method, locals)
  else
    raise TemplateNotFound, "Could not find template at #{template_location}.*"
  end
end.join
 
sent_template



Now this wasn't perfect by a long shot. There was a lot going on here (and I'd personally like to have seen the method refactored). But the interesting part is what happened inside the loop (starting from sent_template = with.map). Unlike ActionView, which figured out the name of the template, got the template object, got the counter name, and so on, Merb limited the activity inside the loop to setting a couple of Hash values and calling a method.

For a collection of 100 partials, this could be the difference between overhead of around 10ms and overhead of around 3ms. For a collection of small partials, this could be significant (and a reason to inline partials that were appropriate to be partials in the first place).

In Rails 3, we've improved performance by reducing what happens inside the loop. Unfortunately,there was a specific feature of Rails that made it a bit harder to optimize this generically. Specifically, you could render a partial with a heterogenous collection (a collection containing Post, Article and Page objects, for instance) and Rails would render the correct template for each object (Article objects render _article.html.erb, etc.). This means that it was not always possible to determine the template to render up front.

In order to deal with this problem, we haven't been able to optimize the heterogenous case completely, but we have made render :partial => "name", :collection => @array faster. In order to achieve this, we split the code paths, with a fast path for when we knew the template, and a slow path for where it had to be determined based on the object.

So now, here's what rendering a collection looks like, when we know the template:

def collection_with_template(template = @template)
  segments, locals, as = [], @locals, @options[:as] || template.variable_name
 
  counter_name  = template.counter_name
  locals[counter_name] = -1
 
  @collection.each do |object|
    locals[counter_name] += 1
    locals[as] = object
 
    segments < < template.render(@view, locals)
  end
 
  @template = template
  segments
end



Importantly, the loop is now tiny (even simpler than what happened in Merb inside the loop). Something else worth mentioning is that in improving the performance of this code, we created a PartialRenderer object to track state. Even though you might expect that creating a new object would be expensive, it turns out that object allocations are relatively cheap in Ruby, and objects can provide opportunities for caching that are more difficult in procedural code.

For those of you want to see the improvements in pictures, here are a few things to look at: first, we have the improvement between Rails 2.3 and Rails 3 edge on Ruby 1.9 (smaller is faster).



And here it is for more expensive operations:



Last we've got a comparison of Rails 3 across four implementations (Ruby 1.8, Ruby 1.9, Rubinius, and JRuby):



You can see that Rails 3 is significantly faster than Rails 2.3 across the board, and that all implementations (including Rubinius!) are significantly improved over Ruby 1.8. All in all, a great year for Ruby!

Next post, I'll talk about improvements in the Rails 3 API for plugin authors—keep an eye out, and as always, leave your comments!


more »

Rails and Merb Merge: The Anniversary (Part 1 of 6) »

Created at: 24.12.2009 00:30, source: Engine Yard Blog, tagged: Technology merb rails Ruby on Rails

A year ago today, we announced that Rails and Merb would merge. At the time, there was much skepticism about the likelihood of the success of this endeavor. Indeed, The most common imagery invoked by those who learned about our plans was a unicorn. At RailsConf last year (well into the effort), both DHH and I used unicorns in our talks, poking fun at the vast expectations we’d set, and the apparent impossibility of achieving everything we’d said we wanted to achieve for 3.0.

A year has gone by, so it’s a good time to reflect on how well we’ve done at achieving those expectations. Over the next few days, I’ll take each bullet point that I provided in my original post, and go into detail about the progress we’ve made on that front.

I’ve given a few recent talks on these topics, so some of you may already have seen some of this, but I wanted to get it down in writing for those who hadn’t. I’ve also added new information, some of which was omitted because it was difficult to explain in a talk, and some of which is too current for any of my recent talks.

Modularity

Rails will become more modular, starting with a rails-core, and including the ability to opt in or out of specific components. We will focus on reducing coupling across Rails, and making it possible to replace parts of Rails without disturbing other parts. This is exactly what Merb means when it touts “modularity”.

We’ve spent a significant amount of time on this step which has been really fruitful. I’ll give a few specific examples.

ActiveSupport

First, we’ve gone through ActiveSupport, making it viable to cherry-pick specific elements. This means that using ActiveSupport’s inflector, time extensions, class extensions, or anything your heart desires is now possible without having to personally track the dependency graph. Here’s an example of what I mean, from the to_sentence method in ActiveSupport from Rails 2.3:

module ActiveSupport

  module CoreExtensions

    module Array

      module Conversions

        def to_sentence(options = {})
          ...
          options.assert_valid_keys :words_connector, :two_words_connector, :last_word_connector, :locale
          ...
        end
      ...
    end
  end
end

As you can see, to_sentence has an implicit requirement on assert_valid_keys, which means that in order to cherry-pick active_support/core_ext/array/conversions, you are forced to work through the file, find any unsatisfied dependencies, and be sure to require them as well. And of course, the structure of these dependencies could easily change in a future version of Rails, so relying on what you’d found would be unsafe. In Rails 3, the top of that same file looks like:

require 'active_support/core_ext/hash/keys'
require 'active_support/core_ext/hash/reverse_merge'
require 'active_support/inflector'

This is because we’ve gone through the entire ActiveSupport library, found the unsatisfied dependencies, and made them explicit. As a result, you can pull out the specific libraries you want for a small project, and not get the full weight of ActiveSupport.

Even better, other parts of Rails now explicitly declare the dependencies they have on ActiveSupport. So for instance, the code that adds logging support to ActionController has the following lines on top:

require 'active_support/core_ext/logger'
require 'active_support/benchmarkable'

This means that all of Rails knows what parts of ActiveSupport are needed. For simplicity, Rails 3 ships with all of ActiveSupport still provided, so you’ll be able to use things like 3.days or 3.kilobytes without interruption. However, if you want more control over what gets included, that’s possible. You can declare config.active_support.bare = true in your configuration and we’ll pull in only the parts of ActiveSupport explicitly needed for the parts of Rails that you use. You’ll still need to include the fancy parts if you want to use them – 3.days wont work out of the box with bare enabled.

ActionController

Another area that really needed an overhaul was ActionController. Previously, ActionController had a number of disparate elements all in one place. When we looked closely, we found that there were really three discrete components masquerading as one.

First, there was the dispatching functionality. This included the dispatcher itself, routing, middleware, and rack extensions. Second there was generic controller code that was meant to be reused elsewhere, and was in fact reused in ActionMailer. Finally, there was the subset of controller code that brought those two concerns together: code that handled requests and responses through a controller architecture.

In Rails 3, each of those components has been separated out. The dispatcher functionality has been moved into ActionDispatch, with the code inside tightened up and really made a conceptual component. The parts of ActionController that were meant to be reused by non-HTTP controllers was moved into a new component called AbstractController, which both ActionController and ActionMailer inherit from.

Finally, ActionController itself has gotten a significant overhaul. Essentially, we’ve isolated every standalone component, and made it possible to start with a stripped-down controller and pull in just the components you want. Our old friend ActionController::Base simply starts with that same stripped-down controller and pulls everything in. For instance, take a look at the beginning of the new version of that class:

module ActionController
  class Base < Metal
    abstract!

    include AbstractController::Callbacks
    include AbstractController::Logger

    include ActionController::Helpers
    include ActionController::HideActions
    include ActionController::UrlFor
    include ActionController::Redirecting
    include ActionController::Rendering
    include ActionController::Renderers::All
    include ActionController::Layouts
    include ActionController::ConditionalGet
    include ActionController::RackDelegation
    include ActionController::Logger
    include ActionController::Benchmarking
    include ActionController::Configuration

All we’re doing here is pulling in every available module, so the default experience of Rails is the same as before. However, the real power of what we’ve done here is the same as what we’ve done in ActiveSupport: every module declares its dependencies on other modules, so you can pull in Rendering, for instance, without having to wonder what other modules need to be included and in what order.

The following is a perfectly valid controller in Rails 3:

class FasterController < ActionController::Metal
  abstract!

  # Rendering would be pulled in by layouts, but I include
  # it here for clarity
  include ActionController::Rendering
  include ActionController::Layouts

  append_view_path Rails.root.join("app/views")
end

class AwesomeController < FasterController
  def index
    render "so_speedy"
  end
end

And then, in your routes, it would be perfectly valid to do:

MyApp.routes.draw do
  match "/must_be_fast", :to => "awesome#index"
end

Essentially, ActionController::Base has become just one way to express your controllers. Think of it like Rails Classic, with the ability to roll your own if you’re not so into that taste. It’s really easy to mix and match too: if you wanted to pull in before_filter functionality to FasterController, we could simply include AbstractController::Callbacks.

Note that without doing anything else, including those modules pulled in AbstractController::Rendering (the subset of rendering functionality shared with ActionMailer), AbstractController::Layouts, and ActiveSupport::Callbacks.

This makes it really possible to trivially pull in just the specific functionality you need in performance-sensitive cases without having to use an entirely different API. If you need additional functionality, you can easily just pull in additional modules or eventually upgrade to the full ActionController::Base without needing to rip anything apart along the way.

This, in fact, is a core idea of Rails 3: there are no monolithic components, only modules that work seamlessly together in a great package of defaults. This allows people to continue using Rails as they have used it successfully in previous versions, but really leverage the codebase for alternative uses. No more functionality locked away in non-reusable forms.

One nice immediate benefit of all of this is that ActionMailer gets all of the functionality of ActionController in a clean, intentional way. Everything from layouts and helpers to filters is using the identical code that ActionController uses, so ActionMailer can never again drift away from the functionality of ActionController (as ActionController itself evolves).

Middleware gets a helping hand too. ActionController::Middleware, which is middleware with all of the powers of ActionController, allows you to pull in whatever ActionController features you want (like Rendering, ConditionalGet, robust Request and Response objects, and more) as needed. Here’s an example:

# The long way
class AddMyName < ActionController::Middleware
  def call(env)
    status, headers, body = @app.call(env)
    headers["X-Author"] = "Yehuda Katz"
    headers["Content-Type"] = "application/xml"

    etag = env["If-None-Match"]
    key = ActiveSupport::Cache.expand_cache_key(body + "Yehuda Katz")
    headers["ETag"] = %["#{Digest::MD5.hexdigest(key)}"]
    if headers["ETag"] == etag
      headers["Cache-Control" = "public"]
      return [304, headers, [" "]]
    end

    return status, headers, body
  end
end
# Using extra Rack helpers
class AddMyName < ActionController::Middleware
  include ActionController::RackDelegation

  def call(env)
    self.status, self.headers, self.response_body = @app.call(env)

    headers["X-Author"] = "Yehuda Katz"

    # but you can do more nice stuff now
    self.content_type = Mime::XML # delegates to the response
    response.etag = "#{response.body}Yehuda Katz"
    response.cache_control[:public] = true

    self.status, self.response_body = 304, nil if request.fresh?(response)

    response.to_a
  end
end
# Using ConditionalGet helpers
class AddMyName < ActionController::Middleware
  # pulls in RackDelegation
  include ActionController::ConditionalGet

  def call(env)
    self.status, self.headers, self.response_body = @app.call(env)

    headers["X-Author"] = "Yehuda Katz"

    self.content_type = Mime::XML
    fresh_when :etag => "#{response.body}Yehuda Katz", :public => true

    response.to_a
  end
end

In all, I really think we’ve delivered on our promise to bring significant modularity improvements to Rails (and then some). In fact, I think the level of success that we’ve had with this version exceeds most people’s expectations of a year ago, and is solidly in golden unicorn territory. Enjoy!

Tomorrow, I’ll talk about bringing performance improvements to Rails 3. Hopefully it won’t go by too fast. :)


more »

Engine Yard hiring developers to help build our cloud »

Created at: 07.04.2009 23:19, source: Brainspl.at, tagged: cloud deployment automation chef merb datamapper nanite aws

I’m looking for a few good folks to join my team. You need to be able to work on site in San Francisco, we can assist with moving expenses for the right candidate.

You would work with my team(currently 5 devs). We do no bs agile style development with pairing where appropriate and test infected mentality . generally we have a fun, tight team and get to work on some of the hardest and most rewarding areas of software development relevant today.

You would be on my team working on http://engineyard.com/solo and it’s successors as well as Engine Yard’s on premises infrastructure.

You would be working on/with the following ruby technologies:

Ruby
Merb
Rails
Sinatra
DataMapper
Nanite
Chef
Event Machine
Many others..

You would be working on the following problem domains:

Scalable Ruby Deployment Architectures
Scalable Cloud Computing Architectures
Scalable Database Architecture
Distributed Computing
Key Value Data Stores
Infrastructure automation
Cloud provider API's
Multi-Cloud portability
Monitoring and alerting systems
Security in the Cloud
Horizontally Scalable Architectures
Many other interesting areas of computing

Familiarity with the following tech is nice but not necessarily required if you can learn fast:

Gentoo Linux
Nginx
Apache
Monit
Daemontools
Mysql
Postgresql
Memcached
Passenger
Mongrel
Thin
SSL Certs
Iptables/Networking
Erlang

If you think you have the “right stuff” and you have the kick ass take names attitude then send a resume with a short intro about who you are and why you are the person we should hire.

ez@engineyard.com


more »

Rails and Merb core team working together »

Created at: 24.12.2008 10:47, source: Rails on the Run - Home, tagged: announcement merb merge rails

This is a huge!


While people still try to find some drama an in hypothetical war between rails and merb.

The Rails team and the Merb team announced working together on a joined version of the 2 frameworks. This is so exciting, nobody believed it could ever happen (I personally, had my serious doubt).

Yehuda had a great post laying down the plan and explaining things in details. Check out David’s post explaining why he wants us to work together and his vision of a better Ruby world.

I have to say that I have been impressed by the Rails core team and especially David (DHH).

I’ve known David for few years now and we had long/heated discussions on topics like i18n/l10n for Rails. David is known to be a very opinionated person. But if you come up with the right arguments, he can be convinced and when that happens, he is willing to move forward and shake things up.

This merge is a concrete example that David and the rest of the Rails team cares about Rails and the Ruby community more than we usually give them credit for. As a unified team, we are going to change the way web development in Ruby is done!

But what does it mean for you?

I put together a FAQ video which, I hope will answer your questions.

<object height="300" width="400"><param /><param /><param /><embed src="http://vimeo.com/moogaloop.swf?clip_id=2607919&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" height="300" width="400"></embed></object>
Matt Aimonetti: message to all merbists

Transcript:

Hi, I’m Matt Aimonetti from the merb core team and as you might have heard, a big announcement was made earlier today.
I did this video to hopefully answer the questions you might have.

Q: So what’s the big news?

  • merb and rails team will work together on the next version of their frameworks
  • merb 2.0 and rails 3.0 share the same common endpoint
  • we realized we now have the same objectives and agreed on all the key principles.
  • merb will provide Rails with agnosticism, modularity, improved performance and a public API.
  • The end product will be called Rails 3.0 but what real matters is that it’s a huge gain for the entire community.

Q: What??? I thought there was a war going on between Rails and merb, what happened?

  • There was no war between rails and merb
  • We created merb because rails was not fitting us
  • We wanted better performance, more choices/ more modularity and a Public API.
  • The Rails team now embraces these concepts and want Rails to follow them, so why not work together?

Q: Wait, does that mean that merb is dead?

  • Absolutely not!
  • merb development won’t stop, we are going to keep on releasing updates until rails 3.0
  • clear migration path, and upgrading to rails 3.0 will be as trivial as upgrading from rails 2.x to Rails 3.0

Q: What does the timeline look like?

We just started getting together and discuss the technical details. We are shooting for a release at RailsConf 2009. However it’s hard to estimate this kind of things so again, that’s just an estimate :)

Q: I just started a merb project, so what now?

I’m sure you had valid reasons to use merb, you needed modularity, performance and a solid API.
Keep on using Merb, we won’t let you down. The good news is that the next version of merb (rails 3.0) will be even awesomer!

Q: What about my client who was looking at using merb for his new project?

If your client is going to be using merb for valid reasons (and not, just because it’s not rails) he should still use merb, but with the full understanding that he/she will end up using Rails in 6 months or so. Again, Rails 3.0 will have what pushed you to use merb.

Q: I’ve been involved with the merb-book, what will happen with this project?

  • rails 3.0 won’t get released right away
  • still need awesome documentation
  • if we look at rails 3.0 as merb 2.0, we can easily imagine how the current work can be extended to the new version.
  • rails team will also include an evangelism team which I will be part of, so will be able to focus more on projects like the book.

Q: I’ve been working on a merb plugin, what should I do?

Keep working on it! We’ll assist you with the migration process and the new solid API.

Q: What if I still have questions?

Come talk with me, or any members from the new team. We’ll be open to hear your questions, worries, frustrations.
merb always valued its developers and we will continue to do so but at a bigger scale.


Concretely, nothing changes for Merb users. People loving Merb should not worry. The way you build merb apps won’t change until merb2.0/rails3.0. We will still work on your favorite framework and improve it.

Lori Holden worked on merb_sequel and we should release a 1.0 release of the plugin in a few days.

I’m sure this news comes as a shock for many of you, but try to not see Rails 3.0 as the way Rails is right now. Imagine a version of Rails with true modularity and agnosticism (sequel, DM and AR will still be supported) and the same type of performance as what you get with Merb. In other words, the rails world is about to discover the power of merb!

Here is what Yehuda explicitly says in his blog post:

  • Rails will become more modular, starting with a rails-core, and including the ability to opt in or out of specific components. [...]
  • We will port all of our performance improvements into Rails. This includes architectural decisions that are big performance wins.[..]
  • As of Rails 3, Rails will have a defined public API with a test suite for that API. [..]
  • Rails will still ship with the “stack” version as the default (just as Merb does since 1.0), but the goal is to make it easy to do with Rails what people do with Merb today.
  • Rails will be modified to more easily support DataMapper or Sequel as first-class ORMs. [..]
  • Rails will continue their recent embrace of Rack, which [..] will improve the state of modular, sharable logic between applications.
  • In general, we will take a look at features in Merb that are not in Rails (the most obvious example is the more robust router) and find a way to bring them into Rails.

Personal perspective

I’m personally really excited about this opportunity. I had a hard time believing that we could work together but I was proved wrong. We have many challenges in front of us, but watching the two teams working together is very reassuring.

I’m also glad to see that we will have a Rails Evangelism team that I will be part of. I strongly believe that one of the many reasons why merb has been so successful is because we work and listen to our community. We have put a tremendous amount of energy trying to understand what you guys need and what you like and dislike. In return, we saw many people working hard on the wiki and the merb-book.

Can you imagine doing that with almost 4 Million Rails developers?

I’m also looking forward to working with a team and reaching to even more people.

Other news related to the merge:

If you have any questions, or if you want me to publicly answer questions on your blog please contact me. I’ll do my best to get back to everyone.


more »

Rails and Merb core team working together »

Created at: 24.12.2008 10:47, source: Rails on the Run - Home, tagged: announcement merb merge rails

This is a huge!


While people still try to find some drama an in hypothetical war between rails and merb.

The Rails team and the Merb team announced working together on a joined version of the 2 frameworks. This is so exciting, nobody believed it could ever happen (I personally, had my serious doubt).

Yehuda had a great post laying down the plan and explaining things in details. Check out David’s post explaining why he wants us to work together and his vision of a better Ruby world.

I have to say that I have been impressed by the Rails core team and especially David (DHH).

I’ve known David for few years now and we had long/heated discussions on topics like i18n/l10n for Rails. David is known to be a very opinionated person. But if you come up with the right arguments, he can be convinced and when that happens, he is willing to move forward and shake things up.

This merge is a concrete example that David and the rest of the Rails team cares about Rails and the Ruby community more than we usually give them credit for. As a unified team, we are going to change the way web development in Ruby is done!

But what does it mean for you?

I put together a FAQ video which, I hope will answer your questions.

<object height="300" width="400"><param /><param /><param /><embed src="http://vimeo.com/moogaloop.swf?clip_id=2607919&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" height="300" width="400"></embed></object>
Matt Aimonetti: message to all merbists

Transcript:

Hi, I’m Matt Aimonetti from the merb core team and as you might have heard, a big announcement was made earlier today.
I did this video to hopefully answer the questions you might have.

Q: So what’s the big news?

  • merb and rails team will work together on the next version of their frameworks
  • merb 2.0 and rails 3.0 share the same common endpoint
  • we realized we now have the same objectives and agreed on all the key principles.
  • merb will provide Rails with agnosticism, modularity, improved performance and a public API.
  • The end product will be called Rails 3.0 but what real matters is that it’s a huge gain for the entire community.

Q: What??? I thought there was a war going on between Rails and merb, what happened?

  • There was no war between rails and merb
  • We created merb because rails was not fitting us
  • We wanted better performance, more choices/ more modularity and a Public API.
  • The Rails team now embraces these concepts and want Rails to follow them, so why not work together?

Q: Wait, does that mean that merb is dead?

  • Absolutely not!
  • merb development won’t stop, we are going to keep on releasing updates until rails 3.0
  • clear migration path, and upgrading to rails 3.0 will be as trivial as upgrading from rails 2.x to Rails 3.0

Q: What does the timeline look like?

We just started getting together and discuss the technical details. We are shooting for a release at RailsConf 2009. However it’s hard to estimate this kind of things so again, that’s just an estimate :)

Q: I just started a merb project, so what now?

I’m sure you had valid reasons to use merb, you needed modularity, performance and a solid API.
Keep on using Merb, we won’t let you down. The good news is that the next version of merb (rails 3.0) will be even awesomer!

Q: What about my client who was looking at using merb for his new project?

If your client is going to be using merb for valid reasons (and not, just because it’s not rails) he should still use merb, but with the full understanding that he/she will end up using Rails in 6 months or so. Again, Rails 3.0 will have what pushed you to use merb.

Q: I’ve been involved with the merb-book, what will happen with this project?

  • rails 3.0 won’t get released right away
  • still need awesome documentation
  • if we look at rails 3.0 as merb 2.0, we can easily imagine how the current work can be extended to the new version.
  • rails team will also include an evangelism team which I will be part of, so will be able to focus more on projects like the book.

Q: I’ve been working on a merb plugin, what should I do?

Keep working on it! We’ll assist you with the migration process and the new solid API.

Q: What if I still have questions?

Come talk with me, or any members from the new team. We’ll be open to hear your questions, worries, frustrations.
merb always valued its developers and we will continue to do so but at a bigger scale.


Concretely, nothing changes for Merb users. People loving Merb should not worry. The way you build merb apps won’t change until merb2.0/rails3.0. We will still work on your favorite framework and improve it.

Lori Holden worked on merb_sequel and we should release a 1.0 release of the plugin in a few days.

I’m sure this news comes as a shock for many of you, but try to not see Rails 3.0 as the way Rails is right now. Imagine a version of Rails with true modularity and agnosticism (sequel, DM and AR will still be supported) and the same type of performance as what you get with Merb. In other words, the rails world is about to discover the power of merb!

Here is what Yehuda explicitly says in his blog post:

  • Rails will become more modular, starting with a rails-core, and including the ability to opt in or out of specific components. [...]
  • We will port all of our performance improvements into Rails. This includes architectural decisions that are big performance wins.[..]
  • As of Rails 3, Rails will have a defined public API with a test suite for that API. [..]
  • Rails will still ship with the “stack” version as the default (just as Merb does since 1.0), but the goal is to make it easy to do with Rails what people do with Merb today.
  • Rails will be modified to more easily support DataMapper or Sequel as first-class ORMs. [..]
  • Rails will continue their recent embrace of Rack, which [..] will improve the state of modular, sharable logic between applications.
  • In general, we will take a look at features in Merb that are not in Rails (the most obvious example is the more robust router) and find a way to bring them into Rails.

Personal perspective

I’m personally really excited about this opportunity. I had a hard time believing that we could work together but I was proved wrong. We have many challenges in front of us, but watching the two teams working together is very reassuring.

I’m also glad to see that we will have a Rails Evangelism team that I will be part of. I strongly believe that one of the many reasons why merb has been so successful is because we work and listen to our community. We have put a tremendous amount of energy trying to understand what you guys need and what you like and dislike. In return, we saw many people working hard on the wiki and the merb-book.

Can you imagine doing that with almost 4 Million Rails developers?

I’m also looking forward to working with a team and reaching to even more people.

Other news related to the merge:

If you have any questions, or if you want me to publicly answer questions on your blog please contact me. I’ll do my best to get back to everyone.


more »