{
    "componentChunkName": "component---src-templates-blog-post-tsx",
    "path": "/blog/2012-12-04-therubyracer-rides-again/",
    "result": {"data":{"blogPost":{"title":"The Ruby Racer Rides Again","slug":"/blog/2012-12-04-therubyracer-rides-again/","authorNodes":[{"name":"Charles Lowell","slug":"/people/charles-lowell/"}],"markdown":{"html":"<h2 id=\"it-began-during-railsconf\" style=\"position:relative;\"><a href=\"#it-began-during-railsconf\" aria-label=\"it began during railsconf permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>It began during RailsConf.</h2>\n<p>My fingers were itching to code, so between sessions I started\ntinkering with some of the more fanciful enhancements to\n<a href=\"https://github.com/cowboyd/therubyracer\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">The Ruby Racer</a> I'd been contemplating as well as wrestling with\na number of long-standing bugs. But what started out as a small\nrefactoring slowly but relentlessly gained momentum until things\nwere completely out of control.</p>\n<p>By all accounts my hands were steady and the work proceeded in an\norderly fashion. Instead, it was <em>I</em> who was out of control.\nPersonally and psychologically I was helpless to stop myself as line\nafter line, class after class unravelled before me --each one more\nrapidly than before. Soon a critical mass was achieved and boom!\nNuclear. A from-scratch rewrite was underway.</p>\n<p>Yes it was a rewrite, but by the time I was aware of it, I was too\ndeeply invested to turn back.</p>\n<p>It's a tichy thing, is a rewrite. Instead of the careful, iterative\napproach that serves as law in our profession, you drop everything\nand sprint towards the cliff in the hope that you can lunge across the chasm in\nin one leap. Once you're in the air there's no going back, and the\npossibility is as thrilling as it is real that, like Icarus, you'll\nhurtle into the abyss... another unsung casualty of hubris.</p>\n<p>The prize of course is a better library that is more stable, has more\nfeatures and is easier to build and install, so if a rewrite it had to be,\nI did the only thing I could do yield myself to it utterly.</p>\n<p>I'm happy to say that it's mostly there there and that, despite some outstanding\nflaws, I'll be releasing the next version shortly. But more on that later.\nFirst, what's new?</p>\n<h2 id=\"stability\" style=\"position:relative;\"><a href=\"#stability\" aria-label=\"stability permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Stability</h2>\n<p>For certain applications therubyracer has been plagued by crashes and memory\nleaks that have limited its usefulness to a much smaller domain than\nnecessary: specifically, low-traffic applications that only instantiate a\nsingle JavaScript context. These problems stemmed from within the library but\nalso from within Ruby itself.</p>\n<p>The Ruby Racer relies heavily on weak references in order to maintain\nreferential integrity between Ruby object and the JavaScript objects they\nrepresent (and vice-versa). Sadly, the <a href=\"http://bugs.ruby-lang.org/issues/show/4168\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">WeakRef implementation on 1.9 is\ncompletely broken</a>. This is unfortunate because functioning weak\nreferences are sometimes a necessary component for building correct\nprograms on platforms with garbage collection. Luckily <a href=\"https://github.com/bdurand/ref\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">there are\nworkarounds</a> which have been deployed while we wait for 2.0.</p>\n<p>But that's not the whole story. It would be a shameful misrepresentatio\nto lay the bulk of the blame on Ruby's door. Distributed garbage collection\nis hard, and The Ruby Racer engaged in all manners of evil hackery and dark\nGC foo in order to prevent cycles of garbage from spanning the Ruby and\nJavaScript VMs. Sadly, this did not work in the general case, and furthermore,\nwas not portable to other Ruby implementations (or even Ruby versions).</p>\n<p>I've come to realize that to solve these memory problems in the general case\nwould require each host Ruby platform, as well as V8, to expose a uniform\ninterface to its garbage collector so that The Ruby Racer can traverse its\nobject graph in order to detect cycles of garbage. In other words \"not\nbloody likely.\"</p>\n<p>As a fallback, I've decided to throw up my hands and eschew GC histrionics in\nfavor of more sane memory management in the C extension combined with an explicit\nteardown mechanism for cases where cycles of garbage do occur. e.g.</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">context = V8::Context.new\ncontext['cycle'] = context #oh no, a vicious cycle!\n\ncontext.dispose() # Gordion knot is cleaved, sir!</code></pre></div>\n<p>In exchange, we get a kinder, gentler racer that works on MRI as well as\nRubinius, and which you'll be able to rely on in your production processes.</p>\n<h2 id=\"resource-constraints\" style=\"position:relative;\"><a href=\"#resource-constraints\" aria-label=\"resource constraints permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Resource Constraints</h2>\n<p>Speaking of production, the upcoming release contains a much more\ncomprehensive coverage of underlying V8 functionality than every before.</p>\n<p>Among other things, you can query the V8 vm for heap usage by young generation,\nold generation as well as absolute heap size including executable memory. Not\nonly that, but you can also place hard caps on each of these numbers. That way\nyou can contain memory usage and keep your processes under control; even in a\nresource constrained environment like Heroku.</p>\n<h2 id=\"a-hopefully-kinder-build\" style=\"position:relative;\"><a href=\"#a-hopefully-kinder-build\" aria-label=\"a hopefully kinder build permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>A (hopefully) kinder build</h2>\n<p>One of the sorest pain-points with The Ruby Racer was the way it built. Prior to\n0.11, it had a hard dependency on the <a href=\"http://bugs.ruby-lang.org/issues/show/4168\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">libv8 rubygem</a> in order to provide the\nactual V8 library. In retrospect, this was a bad idea.</p>\n<p>If you were unable to build the v8 contained in the libv8 gem, then\nyou were completely hosed. You could not use therubyracer at all. Or, if you\nwanted to use a custom v8 patched for security or with tweaked startup data,\nthen you were out of luck. Finally, it raised an unnecessary barrier\nto distributing therubyracer as a binary gem (which I would like to do more of).\nIf you have a binary version, then why do you need to have libv8 at all?</p>\n<p>For these reasons, the dependency on libv8 has been converted to a soft one. If\na compatible version is detected in your rubygems, then it will compile and link\nagainst it. However, if for whatever reason, you do <em>not</em> want to use the libv8\ngem to build, then that is now your prerogative. The Ruby Racer will search\nyour system for v8 just like any other library.</p>\n<p>The only difference is that if you want to use the libv8 gem, then you will have\nto explicitly require a compatible version in your Gemfile.</p>\n<h2 id=\"more-bugs-but-not-on-rubinius\" style=\"position:relative;\"><a href=\"#more-bugs-but-not-on-rubinius\" aria-label=\"more bugs but not on rubinius permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>More bugs, but not on Rubinius</h2>\n<p>There are still some outstanding issues on MRI that emerge under a heavy stress of\nrapid object allocation and deallocation. As far as I can tell they are related to\nto the weakref implementation, wherein MRI gets confused and starts handing back\nreferences to completely unrelated objects. I say \"as far as I can tell\" because the\nsubtleties involved lie beyond the frontier of my understanding of MRI internals.\nGiven my current workload, it is unlikely I will have time to make the necessary\ninvestment in understanding required to completely quash these problems.</p>\n<p>Despite this, I'm releasing the new version anyhow in order to support Rubinius more\nfully and because I think that even on MRI it will solve more problems than it introduces.</p>\n<p>For starters, 0.11 is very stable on Rubinius and that platform is long overdue\nfor a version of therubyracer that doesn't suck. The Rubinius core team, and <a href=\"https://twitter.com/dbussink\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">@dbussink</a>\nin particular, have been very patient and helpful in helping me resolve all the lingering\ncrashes both big and small... even going to the trouble of adding checks and diagnostics\nto the garbage collector just for my sake. They were even willing and often able to\ndiagnose problems I was having on MRI in order to make the library for everybody.\nIf anything, I feel that they deserve a functioning JavaScript environment and it wouldn't\nbe fair for me to withhold it from them.</p>\n<p>On the MRI front, I still think that closing some of the loopholes in the memory management,\nthe enhanced extensibility, and better build make it worth releasing anyway. I've been\nrecommending people to upgrade to the beta for almost 3 months and it is almost always the\nright decision. Given that I have neither the time nor the inclination to support what I now\nconsider to be the legacy release, I think it's high time to either shit or get off the\nproverbial pot.</p>\n<p>If you, or anybody you know has a deep knowledge of MRI internals and would be willing to help\nme address these issues as well as others that may arise, I would love to work with you to\nknock 'em down.</p>\n<p>So this is why I'm releasing version 0.11.0 of The Ruby Racer today. Of course, I may\ncome to quickly regret it, but that's what <code class=\"language-text\">gem yank</code> is for right?</p>","frontmatter":{"date":"December 04, 2012","description":null,"tags":["javascript","ruby","therubyracer"],"img":null}}}},"pageContext":{"id":"03bafe22-c7a0-5b40-ab44-6f7a0bcaf9d4"}},
    "staticQueryHashes": ["1241260443"]}