<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">
  <title>rkh.im</title>
  <id>http://rkh.im</id>
  <updated>Tue, 21 Feb 2012 10:40:45 GMT</updated>
  <author>
    <name>Konstantin Haase</name>
  </author>
  <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/rkh" /><feedburner:info uri="rkh" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry>
    <title>Strengths and Weaknesses of Seaside</title>
    <link rel="alternate" href="http://feedproxy.google.com/~r/rkh/~3/w1_6kt10vPE/seaside" />
    <id>/seaside</id>
    <published>2010-08-25</published>
    <updated>2010-08-25</updated>
    <author>
      <name>Konstantin Haase</name>
    </author>
    <content type="html">&lt;p&gt;&lt;em&gt;This is an excerpt from my bachelor thesis.&lt;/em&gt;&lt;/p&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        &lt;h2&gt;Core principles&lt;/h2&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        &lt;p&gt;&lt;a href="http://seaside.st/"&gt;Seaside&lt;/a&gt;'s approach to web development differs from most other web
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        frameworks, such as Django or Ruby On Rails, by explicitly breaking
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        with common patterns and principals the web is built upon, such as
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        being stateless, having meaningful, maybe even restful URLs or using
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        template systems.&lt;/p&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        &lt;p&gt;When doing web development you often have to work with the construct of a session, that
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        allows one to keep state in between requests made from the same
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        browser session. Usually the session is serialized and stored in a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        cookie or a database. Seaside takes advantage of Smalltalk's image
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        based nature by simply keeping the session as an object in the
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        currently active process.&lt;/p&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        &lt;p&gt;This eliminates the overhead of serializing
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        every object in the session and the need to keep the number of objects
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        kept by the session small. Seaside goes even further by storing
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        closures and continuations in the session.&lt;/p&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        &lt;p&gt;While most other frameworks use the session as little as possible, in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        Seaside it is used for nearly everything. It solely depends on the
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        state of your session what page is displayed. Usually every Seaside
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        application features a single entrance point, a so called root
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        component.&lt;/p&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        &lt;p&gt;User navigation is realized by storing continuations and
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        callbacks (closures) for the currently displayed page. User
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        interaction will then trigger any associated callbacks, thereby
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        changing the session's state, and then re-render the possibly changed
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        content.&lt;/p&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        &lt;h2&gt;Advantages over other web frameworks&lt;/h2&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        &lt;p&gt;This gives some advantages over classic web development. Applications,
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        though written for the web, are developed in a way rather similar to
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        desktop applications. Interactive websites, also known as Rich
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        Internet Applications, can rapidly be developed.&lt;/p&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        &lt;p&gt;In the prototyping phase or when developing small sites, using the
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        image for storing data eliminates any need for implementing a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        persistence layer, like an object-database-mapping mechanism.&lt;/p&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        &lt;p&gt;Working on such a high abstraction level compared to normal web
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        development encourages the developer to use object orientation and
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        decoupling on other levels than when working with other web
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        frameworks. Rather than thinking of constructs and working with object
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        representing requests, streams, cookies or URLs, websites are defined
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        by components, callbacks and canvases. This can also encourage a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        creativity, since it requires developers to think outside of their
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        common patterns.&lt;/p&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        &lt;h2&gt;Downsides of developing with Seaside&lt;/h2&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        &lt;p&gt;There are some downsides one has to be aware of when choosing
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        Seaside. Due to the session based nature and the close coupling of
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        "rendering", it is rather
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        complicated to implement public APIs. In many cases Smalltalk
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        developers fall back to other libraries and protocols to accomplish
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        this.&lt;/p&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        &lt;p&gt;When developing software with Seaside, the commonly
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        used path is to write in Smalltalk whatever can be written in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        Smalltalk. This is especially true as Seaside is able to generade some
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        JavaScript from Smalltalk, and tools like Glorp do the same for
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        SQL. This is rather cosy for the developer, who probably favors
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        Smalltalk over the other languages anyway.&lt;/p&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        &lt;p&gt;However, this poses the threat of doing computation in the Seaside
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        image, that could usually be done in the web browser or at database
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        level. Moreover, as this results in changes to the HTML output more
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        often than would be necessary when filling in content via JavaScript,
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        this also conflicts with established caching techniques. The latter is
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        not much of  an issue, since HTTP level caching is not feasible with
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        Seaside, as will be discussed in a moment.&lt;/p&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        &lt;p&gt;Seaside applications usually also conflict with established usage
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        patterns. Tabbed browsing is imposible, so is storing bookmarks for
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        any page besides the entrance page. If a user shares a link with
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        another user, not only might that link not work when the current
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        session expires. This usually happens 10 minutes after the
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        last HTTP request.&lt;/p&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        &lt;p&gt;If the session is not yet expired, the other
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        user opening the link will end up in the same session as the one
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        sharing the link with him or her. This will not only lead to
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        unexpected behavior, but represents a major security risk.&lt;/p&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        &lt;h2&gt;Seaside and scalability - deployment issues to be aware of&lt;/h2&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        &lt;p&gt;There are also implications on the infrastructure level, especially
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        when using reverse proxies. At the server side two types of proxies are commonly
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        used: caches and load balancers.&lt;/p&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        &lt;p&gt;HTTP caches are simply not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        feasible with Seaside. Techniques like the ETag, Last-Modified
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        and Cache-Control HTTP headers are unusable, since they rely on
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        the same content being available under the same URI for multiple
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        requests. Only application layer caching is an option, but it lacks
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        general Seaside solutions and does not keep requests from reaching the
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        image in the first place.&lt;/p&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        &lt;p&gt;Although it would be possible to cache a response, the same HTTP
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        request is extremely unlikely to reoccur and the cache would only
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        allocate additional system resources, increasing deployment costs
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        even more.&lt;/p&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        &lt;p&gt;Load balancers are rather important when scaling web
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        applications. When running a web application you usually do not want
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        to start an application process for every incoming request. Therefore,
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        in a simple setup, one process, an application server, is started and
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        all incoming requests are handled by this process.&lt;/p&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        &lt;p&gt;The Seaside equivalent is starting a Smalltalk image with Seaside. However,
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        increasing load might have a major performance impact on the
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        image. Therefore you often want to launch multiple images on the same
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        computer or even multiple computers each running at least one instance
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        of your application and distribute load equally among them.&lt;/p&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        &lt;p&gt;This is where the load balancer comes in. The load balancer listens for any
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        incoming requests and forwards them as equally distributed as possible
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        to the different images. To reduce overhead the load balancer has to
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        be as fast as possible. Larger setups therefore use hardware load
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        balancers working on ethernet level.&lt;/p&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        &lt;p&gt;For distribution, the proxy often
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        relies on round robin, and URI based sharding, as these algorithmes
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        are simple, efficient and can be implemented at a very low level. As
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        for the same reasons tabs and bookmarks are not usable, you cannot
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        rely on URI based sharding.&lt;/p&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        &lt;p&gt;Load balancing is a major concern when deploying Seaside
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        applications, since most Smalltalk implementations rely on green threads
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        and most Seaside application are not thread-safe. A small number of
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        users accessing the application simultaneously will already result in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        a noticeable increase of response time.&lt;/p&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        &lt;p&gt;When having identical application servers, round robin is the simples
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        way one can imagine to distribute load among them: The first request
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        is forwarded to the first application server, the second to the
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        second, and so on. Until you reach the last app server and start with
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        the first server again. Without additional tools, this approach is not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        usable with Seaside, as requests from a single browser session always
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        have to be forwarded to the same application server.&lt;/p&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        &lt;p&gt;The common approach to address this issue is to use an object database, in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        most cases the proprietary Gemstone/S system, to persist the current
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        session and thus share it over the network among all application
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        servers. While this works remarkably well, it comes with the large
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        overhead of synchronizing the session and all referenced objects
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        (including the closures and continuations) for each and every
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        request.&lt;/p&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        &lt;p&gt;Advanced load balancers do not strictly rely on round robin, but track how
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        many outstanding requests the individual application servers have or
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        how low their response time is, and distribute incoming requests
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        accordingly.&lt;/p&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        &lt;p&gt;An alternative approach is to always forward requests from the same
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        client to the same application server. While this approach works even
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        without sharing sessions among images, it needs additional overhead
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        and does not distribute load as equally as round robin or any similar
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        approach.&lt;/p&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        &lt;p&gt;Imagine one user would be all a single image could
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        handle. In that case all users would have to be equally active to
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        distribute load perfectly among the servers. Moreover, if you have
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        six users on five application servers, the load balancer would have to
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        forward two users to the same server.&lt;/p&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        &lt;p&gt;To solve the performance issues of those two users, a system
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        administrator could decide to start yet another application server and
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        hook it into the load balancer. However, unless a new user appears,
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        that application server will never be used, as users are always
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        forwarded to the same application servers. If one application server
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        crashes, the load balancer will no longer be able to serve to users
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        previously using that server.&lt;/p&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        &lt;p&gt;In a real world example you would therefore configure the load
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        balancer to only forward to the same image in the most cases, with the
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        ability of switching images. Unless you are willing to risk losing the
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        session, that would mean sharing sessions again, but lower the
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        synchronization overhead.&lt;/p&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        &lt;p&gt;By design, this overhead would still be larger than for any web
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        framework embracing web patterns like REST, and makes scaling Seaside
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        a hard task to accomplish.&lt;/p&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        &lt;h2&gt;Why Seaside?&lt;/h2&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        &lt;p&gt;Despite the scalability issues just discussed, we decided to use
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        Seaside. As a powerful web framework it allowed us to easily implement
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        the infrastructure described earlier.&lt;/p&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        &lt;p&gt;Another important factor was that we should favor
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        technologies our external partners were using themselves. This largely
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        influenced our decision towards
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        &lt;a href="http://www.cincomsmalltalk.com/main/products/visualworks/"&gt;VisualWorks&lt;/a&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        and &lt;a href="http://www.glorp.org/"&gt;Glorp&lt;/a&gt;.&lt;/p&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        &lt;p&gt;The only remaining competitor in for this setup would have been the
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        &lt;a href="http://www.iliadproject.org/"&gt;Iliad&lt;/a&gt; web framework, which is commonly
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        used with &lt;a href="http://smalltalk.gnu.org/"&gt;Gnu Smalltalk&lt;/a&gt; rather
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        than VisualWorks. We therefore assumed better support for
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        Seaside. Moreover, our customer was also developing applications with
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        Seaside, which made it a perfect candidate for the project.&lt;/p&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        &lt;p&gt;Fortunately, scalability was not a concern, as the system will
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        probably only have one or two users accessing it simultaneously.&lt;/p&gt;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        &lt;img src="http://feeds.feedburner.com/~r/rkh/~4/w1_6kt10vPE" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://rkh.im/seaside</feedburner:origLink></entry>
  <entry>
    <title>Reloading Ruby Code</title>
    <link rel="alternate" href="http://feedproxy.google.com/~r/rkh/~3/V3mRgMoBKt0/code-reloading" />
    <id>/code-reloading</id>
    <published>2010-08-30</published>
    <updated>2010-08-30</updated>
    <author>
      <name>Konstantin Haase</name>
    </author>
    <content type="html">&lt;p&gt;As the core of my &lt;a href="http://www.rubysoc.org"&gt;Ruby Summer Of Code&lt;/a&gt; project, I have partly &lt;a href="http://github.com/rkh/rails"&gt;rewritten&lt;/a&gt; &lt;code&gt;ActiveSupport::Dependencies&lt;/code&gt;. I will give an introduction to common reloading strategies and their implementation and discuss my changes to &lt;code&gt;Dependencies&lt;/code&gt;. Even though this part of ActiveSupport is hidden away and not well known, all Rails developers rely on its proper functioning, as it is responsible for autoloading and reloading Ruby code. It is also responsible for producing error messages like "A copy of Something has been removed from the module tree but is still active!" or "Object is not missing constant Something!". But before focusing on &lt;code&gt;Dependencies&lt;/code&gt;, let's talk about the topic in general.&lt;/p&gt;

&lt;p&gt;In this article I will focus on reloading code, since autoloading code is rather simple: You define a &lt;code&gt;const_missing&lt;/code&gt; hook, which is triggered whenever an undefined constant is used. Map the constant name to a path (with &lt;code&gt;Dependencies&lt;/code&gt;, &lt;code&gt;Foo::BarBlah&lt;/code&gt; will be mapped to &lt;code&gt;foo/bar_blah&lt;/code&gt;) and search for that file inside a list of directories, in that case &lt;code&gt;Dependencies.autoload_paths&lt;/code&gt; and, for files that should be autoloaded but not reloaded, &lt;code&gt;Dependencies.autoload_once_paths&lt;/code&gt;. Some other implementations use Ruby's &lt;code&gt;$LOAD_PATHS&lt;/code&gt;, which has the advantage of simply trying to &lt;code&gt;require 'foo/bar_blah'&lt;/code&gt; instead of having to search for a matching file by hand. That way autoloading constants from gems or other formats (i.e. &lt;code&gt;foo.so&lt;/code&gt; instead of &lt;code&gt;foo.rb&lt;/code&gt;) just works. On the other hand this may easily lead to loading other files than intended and reloading files that should not be reloaded.&lt;/p&gt;

&lt;script src="https://gist.github.com/533770.js?file=simple_autoloader.rb"&gt;&lt;/script&gt;


&lt;p&gt;You might have already noticed that such an autoloading approach is working on two different levels: Constants and files. The artificial mapping from constants to files is present in most Ruby project, but it is not a low-level Ruby feature. Neither is code reloading. However, especially in Rails-land, reloading is assumed to just work. That is impossible by design. But there are a couple of different approaches trying to get you as close as possible. The key design decisions are &lt;em&gt;when&lt;/em&gt; to reload &lt;em&gt;what&lt;/em&gt; code and &lt;em&gt;how&lt;/em&gt; to do that. Of these decisions, when to reload is the easiest one, as it does not bring any implications for the code that is reloaded. The reloader can be triggered on any file changes or on specified points/events in your program flow, or a combination of the two. In a web app, you probably only want to reload code on a new request. What code you should reload heavily depends on how you are reloading code.&lt;/p&gt;

&lt;p&gt;In the following I will mainly focus on reloading &lt;a href="http://rack.rubyforge.org/"&gt;Rack&lt;/a&gt; applications. I will avoid going into how Rack works. I don't think you have to understand every juicy detail, but if you have no clue what Rack does, now would be a good time to check it out. A lot of the strategies and libraries described here should also be usable for other applications. However, if you're level of interest in Ruby and Rails has brought you as far as this blog post, you &lt;em&gt;really&lt;/em&gt; should get to know Rack.&lt;/p&gt;

&lt;h2&gt;Abusing Open Classes&lt;/h2&gt;

&lt;script src="https://gist.github.com/544919.js?file=open_class.rb"&gt;&lt;/script&gt;


&lt;p&gt;The concept of Ruby's &lt;a href="http://rubylearning.com/satishtalim/ruby_open_classes.html"&gt;open classes&lt;/a&gt; is demonstrated in the above example. You might already know this technique, especially either from &lt;a href="http://www.infoq.com/articles/ruby-open-classes-monkeypatching"&gt;monkey-patching&lt;/a&gt; other modules/classes or from using modules as &lt;a href="http://ruby-doc.org/docs/ProgrammingRuby/html/tut_modules.html"&gt;namespaces&lt;/a&gt;. It can also be used for reloading. About anything that can be defined in Ruby, can also be redefined at runtime.&lt;/p&gt;

&lt;p&gt;Imagine you have a Rack application called &lt;code&gt;Foo&lt;/code&gt; in &lt;code&gt;foo.rb&lt;/code&gt;. If you load &lt;code&gt;foo.rb&lt;/code&gt; twice, then the definition of &lt;code&gt;Foo&lt;/code&gt; monkey-patches itself. If one method was changed in-between the first and the second loading of &lt;code&gt;foo.rb&lt;/code&gt;, the second version will override the first. If a method did not change, it will be overridden with an unchanged version, which is about the same as not overriding it. Well, except for the fact that it will invalidate any method caches and revert any inlining which might have occurred thus far. But the method's implementation will remain the same. This is not only extremely simple, but as it turns out also rather fast. If you want to reload &lt;code&gt;foo.rb&lt;/code&gt; on every request you could set up a simple middleware for that:&lt;/p&gt;

&lt;script src="https://gist.github.com/544921.js?file=reload_foo.ru"&gt;&lt;/script&gt;


&lt;p&gt;However, this is not &lt;code&gt;require&lt;/code&gt;-friendly. Even if &lt;code&gt;foo.rb&lt;/code&gt; requires &lt;code&gt;bar.rb&lt;/code&gt;, only &lt;code&gt;foo.rb&lt;/code&gt; will be reloaded. One solution would be to use &lt;code&gt;load&lt;/code&gt; instead of &lt;code&gt;require&lt;/code&gt;. However, we want to keep the reloader as invisible as possible. Moreover, this would make reloading &lt;code&gt;bar&lt;/code&gt; only if it changed impossible, as it will be reloaded whenever &lt;code&gt;foo&lt;/code&gt; is reloaded. One option we could use for now is to remove &lt;code&gt;bar&lt;/code&gt; from &lt;code&gt;$LOADED_FEATURES&lt;/code&gt;. That way &lt;code&gt;require 'bar'&lt;/code&gt; would load it again. But now &lt;code&gt;bar&lt;/code&gt; will not be reloaded unless &lt;code&gt;foo&lt;/code&gt; is reloaded. A better way would be to actively reload &lt;code&gt;bar&lt;/code&gt;. The example below reloads any files that where loaded and have changed. We can use &lt;code&gt;mtime&lt;/code&gt; for checking if I file changed&lt;/p&gt;

&lt;script src="https://gist.github.com/549533.js?file=reload_world.ru"&gt;&lt;/script&gt;


&lt;p&gt;Note however, that this really includes &lt;em&gt;any&lt;/em&gt; files that have been loaded, even if those are in a gem or the standard library. However, those files usually do not change. Still, this approach might not be useful for bigger apps, as there are files you might not want to reload even if they changed (think initializers). In case this approach is exactly what you want, there is a Rack middleware doing exactly this: &lt;a href="http://github.com/rack/rack/blob/master/lib/rack/reloader.rb"&gt;Rack::Reloader&lt;/a&gt;. Not only does it also include error handling and has some nifty features like the ability to set a cool down phase, you probably have it already installed, as it ships with Rack. Combine it with the autoloader code from above and you got Dependencies Lite™.&lt;/p&gt;

&lt;p&gt;For smaller or well written applications this will work perfectly fine, but you will not be able to use it for a Rails or even a Sinatra app. First, instance and class variables don't get invalidated:&lt;/p&gt;

&lt;script src="https://gist.github.com/549586.js?file=old_vars.rb"&gt;&lt;/script&gt;


&lt;p&gt;The body gets reevaluated:&lt;/p&gt;

&lt;script src="https://gist.github.com/549586.js?file=double_alias.rb"&gt;&lt;/script&gt;


&lt;p&gt;Inheritance cannot be changed:&lt;/p&gt;

&lt;script src="https://gist.github.com/549586.js?file=superclass_mismatch.rb"&gt;&lt;/script&gt;


&lt;p&gt;Methods and constants cannot be removed (at least not by removing them):&lt;/p&gt;

&lt;script src="https://gist.github.com/549586.js?file=remove_method.rb"&gt;&lt;/script&gt;


&lt;p&gt;While the last one is usually not a big issue, the other two make it unusable for Rails. Sinatra will keep the old routes and append the modified ones on a reload. To solve this, you can call &lt;code&gt;Sinatra::Application.reset!&lt;/code&gt;. This will only work if you always reload all files. If you want to have partial reloading, try &lt;a href="http://github.com/rkh/sinatra-reloader"&gt;Sinatra::Reloader&lt;/a&gt;. But still, for your own code you should be aware of these issues. A rule of thumb: Using open classes should work just fine if you are willing to manually restart your application in case one of the above issues should occur and if you favor inheritance and mixins over &lt;code&gt;alias_method_chain&lt;/code&gt;, write your files so that executing them twice does not do any harm and you avoid black magic. You probably don't if you are developing a Rails app. You probably do if you are developing a Sinatra or Rack app.&lt;/p&gt;

&lt;h2&gt;Actually restarting your application&lt;/h2&gt;

&lt;p&gt;OK, so apparently relying on open classes is not usable without constrains. One solution that should work without restrictions would be to actually restart the application instead of reloading just some files. Think about it: It's what you would probably do manually if you're application has no reloading baked in. The implementations usually rely on &lt;a href="http://www.kernel.org/doc/man-pages/online/pages/man2/fork.2.html"&gt;fork&lt;/a&gt;. The strategy is simple: Load everything that should not be reloaded, fork and load everything that should be reloaded. Answer requests from that fork. For reloading: Kill the fork, fork away and again, load everything that should be reloaded. The main issue is watching for changes.&lt;/p&gt;

&lt;p&gt;As reloading is triggered from the outside, you have no clue what files are loaded. One strategy would be to again simply reload on every request. &lt;a href="http://github.com/rtomayko/shotgun"&gt;Shotgun&lt;/a&gt; does this. Another option would be to simply watch the current directory for any changes. A general purpose implementation would be &lt;a href="http://github.com/alexch/rerun"&gt;rerun&lt;/a&gt;. Since rerun is intended to be usable with any application, not just Rack apps, it does lack the preloading feature. Therefor reloading probably occurs a lot less than with shotgun, but takes longer.&lt;/p&gt;

&lt;p&gt;My favorite implementation of this strategy is &lt;a href="http://namelessjon.posterous.com/magical-reloading-sparkles"&gt;"Magical Reloading Sparkles"&lt;/a&gt; by Jonathan D. Stott (aka namelessjon). Unicorn has a signal-based redeployment mechanism. Jonathan's code will trigger it on any code change and cause unicorn to kill and refork all workers. In contrast to shotgun it is also easily possible to specify exactly which code should be preloaded.&lt;/p&gt;

&lt;p&gt;So, why not use this approach? As it does a lot more work under the hood (besides reloading more code than the other approaches, it also fires a new system process) and eats more resources, it is generally slower. I would still recommend it for complex applications, if it only reloads on changes or for really small apps that fire up instantly. Under no circumstances would I recommend using shotgun for a Rails app, but for small Sinatra apps it should be acceptably fast. The main issue, however, is portability: Unix forking is not available on Windows nor JRuby, neither is Unicorn. Offering it as default strategy for Rails would limit official support to Unix and MRI. Note that it &lt;a href="http://github.com/rtomayko/shotgun/issues/closed#issue/13/comment/171837"&gt;would probably be possible&lt;/a&gt; to implement something similar for Windows.&lt;/p&gt;

&lt;h2&gt;Replacing Constants&lt;/h2&gt;

&lt;p&gt;We can do something similar to restarting the app: Remove the old constants before reloading. That way, the old code does not survive: No old instance variables or methods lying around, aliasing works as the body will only be reloaded once per constant incarnation, and since the constant will be redefined instead of reopened on every reload, we can even change its superclass:&lt;/p&gt;

&lt;script src="https://gist.github.com/555026.js?file=remove_const.rb"&gt;&lt;/script&gt;


&lt;p&gt;Let's try to use that:&lt;/p&gt;

&lt;script src="https://gist.github.com/555031.js?file=remove_const.ru"&gt;&lt;/script&gt;


&lt;p&gt;The above gist also points to one of the main issues of this approach: Invalidating references. When using open classes, &lt;code&gt;Foo&lt;/code&gt; always referenced the same object, it just evolved. Now &lt;code&gt;Foo&lt;/code&gt; is a different object before and after each reload.&lt;/p&gt;

&lt;p&gt;If you pass &lt;code&gt;Foo&lt;/code&gt; to &lt;code&gt;run&lt;/code&gt;, &lt;code&gt;Rack::Builder&lt;/code&gt; will use the object passed, which would remain unchanged on the next reload. By wrapping it a new constant lookup will be triggered on every request and thus changes will be picked up. It gets even worse as soon as you realize that the same goes for instances:&lt;/p&gt;

&lt;script src="https://gist.github.com/555145.js?file=surviving_instances.rb"&gt;&lt;/script&gt;


&lt;p&gt;This cannot be fixed entirely. However, it is possible to alleviate these problems.&lt;/p&gt;

&lt;h2&gt;The Rails Way&lt;/h2&gt;

&lt;p&gt;Imagine you where able to remove everything and load all from scratch. That way no old references would survive and no constants could be kept alive. In a nutshell, this is what Rails is trying to do, except, not really. As mentioned above, reloading everything might not be what you want. You might lose state or you even might execute files twice that should not be run twice otherwise. Therefore ActiveSupports divides all constants into two groups: The part that should be reloaded and the part that should not be reloaded. As a rule of thumb the reloadable constants are your app code (models, controllers, extra, etc) and the rest is kept (lib, initializers, external dependencies, etc).&lt;/p&gt;

&lt;p&gt;Everything works fine if you only reference reloadable constants from other reloadable constants (at least if the references would otherwise survive to the next request and would be reused). In order to achieve this, it might be necessary to add constants explicitly to the reloadable pool. This is possible by calling &lt;code&gt;Module#unloadable&lt;/code&gt; on the constant. Note however that marking a constant as reloadable will essentially cause the constants' source file to be reloadable, so if it has any side-effects besides defining the constants, those will reoccur on any request.&lt;/p&gt;

&lt;p&gt;The hard thing is to track which constants belong to what pool. ActiveSupport creates a watch stack for that. It tracks which constants are already known and is able to return a list of new constants for a block of code. It then hooks this mechanism into the autoloading code, require and load. Autoloaded constants will automatically be added to the reloadable pool. However, if the file defining the constant requires other files, ActiveSupport has to be careful to only add the autoloaded constant to the pool, not necessarily its dependencies. Another threat is accidentally loading a file twice before removing its constant, as in that case you would have the issues of the open class approach you were trying to get rid off. ActiveSupport therefore juggles with multiple lists besides the watch stack to track all files that have ever been autoloaded, all files that have been loaded since the last reload ("ActiveSupport::Dependencies.clear", btw), all automatically loaded constants since the last reload and all constants explicitly marked for reload. Also, combinations of those lists are used extensively.&lt;/p&gt;

&lt;p&gt;ActiveSupport removes all reloadable constants after each request and relies on the autoloading hook to reload any required constants. That way on reach request only the constants needed to serve the page should be loaded. In production mode, constants will simply not be removed and autoloading will happen in an eager manner (before the app starts serving), since autoloading is not thread-safe. If loading a file defining a constant raises an error, ActiveSupport also takes care of removing that constant again, thus avoiding "broken" constants.&lt;/p&gt;

&lt;h2&gt;The Rails Way, reloaded&lt;/h2&gt;

&lt;p&gt;ActiveSupport 3.0, even though a lot less than 2.3.5 did, either blows up in your face or does not even mind if anything went wrong. This was the initial motivation for my project proposal. My goal was to reduce error messages. In order to do that, I changed the inner architecture of &lt;code&gt;ActiveSupport::Dependencies&lt;/code&gt; away from a procedural, list juggling to an object oriented approach where every constant has a wrapper knowing whether it is already activated, it is reloadable, and how and when to reload it. At the end of each request still all constants are removed, but the wrappers are kept. Now, the wrapper can decide whether to restore the wrapped constant or to reload it from source.&lt;/p&gt;

&lt;p&gt;In order to do so the developer can choose a reloading strategy. This is probably only relevant for plugin or middleware developers (due to extensive reference keeping, the constant removing approach is rather annoying when writing Rack middleware). The default strategy is the world reloader. The world reload will all cause all constants to be reloaded if a single file referencing a constant with this strategy was changed. This is essentially the same as the current Rails strategy plus checking for changes. ActiveSupport can also pretend a change occurred on every request and skip the &lt;code&gt;mtime&lt;/code&gt; checking. This is an advantage if you have a setup where loading files is rather cheap and checking &lt;code&gt;mtimes&lt;/code&gt; is expensive. Another strategy best set on per constant level, is the open class strategy. It is activated via &lt;code&gt;unloadable :monkey_patching&lt;/code&gt;. If you do so, changing that file will only reload the constant defined in it and restore the constant before reloading it, thus using the open class and keeping all references to that class intact. A third strategy, that is rather experimental, tries to divide the reloadable pool into smaller sub-pools, reloading only the pools affected by file changes. As Yehuda Katz pointed out, this almost always works in demo scenarios but probably fails when tried for real world cases. It is of course also possible to change the default strategy. Such sub-pools are created by associations, &lt;code&gt;require&lt;/code&gt;, &lt;code&gt;require_dependency&lt;/code&gt; and explicitly by &lt;code&gt;Module#associate_with&lt;/code&gt;. I therefore named it sloppy reloading. Since every strategy is just a mixin, plugin developers doing a lot of rails core work, or developers of other frameworks using ActiveSupport (think Padrino) could easily apply their own strategy (&lt;code&gt;unloadable MyLib::MyStrategy&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;But how does this help with reducing errors? The wrapper approach allows easier tracking of what is happening to a constant. The wrapper has hooks to whenever a constant is added or updated, which reduces the likelihood of a "is already activated" or "is not missing constant" error. Moreover, it shifts errors from the autoloading point to the moment old references are actually used. A old reference no one is touching anymore does no harm. My branch therefore modifies the old constant to be a proxy for the new one as soon as it is replaced by another version. In most cases this will not cause an error but redirect the methods and result in the behavior expected if you would not be aware of the reloading that's going on under the hood. This even works when including modules, as Ruby relies on &lt;code&gt;append_features&lt;/code&gt;, which will also be delegated to the new constant.&lt;/p&gt;

&lt;p&gt;Another issue dealt with is using require on reloadable files. Usually, developers are told to simply avoid &lt;code&gt;require&lt;/code&gt; and use &lt;code&gt;require_dependency&lt;/code&gt; instead. If you require a file containing an explicitly reloadable constant without referencing that constant, it will only be loaded the first time. At that point Ruby adds the file to &lt;code&gt;$LOADED_FEATURES&lt;/code&gt; and will not load it again on a require. After the request finished, ActiveSupport will remove the constant. On a reload you might expect require to load the file or the constant to be defined and then try to access the constant implicitly. In that case you will not be able to reach the constant. The patched version of ActiveSupport therefore takes care of removing files from the &lt;code&gt;$LOADED_FEATURES&lt;/code&gt; if the constant is removed. Tracking such events based on the list architecture would have been a nightmare.&lt;/p&gt;

&lt;p&gt;One last, technically minor issue, is offering an alias for &lt;code&gt;unloadable&lt;/code&gt;. A lot of developers I know initially seem rather confused by &lt;code&gt;unloadable&lt;/code&gt;, sometimes even assuming it does the exact opposite (as the constant it "not loadable"). I therefore added an alias I rather prefer: &lt;code&gt;reloadable&lt;/code&gt;, especially when used with a strategy: &lt;code&gt;reloadable :sloppy&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;Numbers, please&lt;/h2&gt;

&lt;p&gt;Lies, damned lies, and statistics, so here we go. In a simple Sinatra application, I get the following numbers:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt; &lt;/th&gt;
      &lt;th&gt;no changes&lt;/th&gt;
      &lt;th&gt;file changed&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;th&gt;No Reloader&lt;/th&gt;
      &lt;td&gt;0.0044671058654&lt;/td&gt;
      &lt;td&gt;-&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;Rack::Reloader&lt;/th&gt;
      &lt;td&gt;0.0231933116912&lt;/td&gt;
      &lt;td&gt;0.0236261129379&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;Sinatra::Reloader&lt;/th&gt;
      &lt;td&gt;0.0088394482930&lt;/td&gt;
      &lt;td&gt;0.0090538899103&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;ActiveSupport&lt;/th&gt;
      &lt;td&gt;0.0207427183787&lt;/td&gt;
      &lt;td&gt;0.0207780686060&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;ActiveSupport Reloaded&lt;/th&gt;
      &lt;td&gt;0.0147878090540&lt;/td&gt;
      &lt;td&gt;0.0208899911244&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;Shotgun&lt;/th&gt;
      &lt;td&gt;0.9925425291061&lt;/td&gt;
      &lt;td&gt;1.0038710657755&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;Magical Reloading Sparkles&lt;/th&gt;
      &lt;td&gt;0.0044739915830&lt;/td&gt;
      &lt;td&gt;0.9384773521974&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;


&lt;p&gt;In a simple Rails 3.0 app serving a page took 0.00793675 seconds, while with my RSoC branch it took 0.00379425 seconds.
Note that you might want to disable &lt;code&gt;mtime&lt;/code&gt; checking on JRuby, as it is about 10 times slower than on MRI and 5 times slower than on Rubinius. If it is worth checking the &lt;code&gt;mtime&lt;/code&gt; on JRuby really depends on how long your files take to load. If you do a lot of instance variable caching and such you might still prefer checking for changes.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/rkh/~4/V3mRgMoBKt0" height="1" width="1"/&gt;</content>
  <feedburner:origLink>http://rkh.im/code-reloading</feedburner:origLink></entry>
</feed>

