TearSnow FanS

Why Nobody Should Use Rails For Anything, Ever

  • In my recent post detailing my impressions of Go (the language), I took the following swipe at Rails:

    Independent of ruby, I see Rails as the emperor with no clothes on. A subject for another post, but I will try my damndest to steer clear of it in the future.

    I was called out on Hacker News for being so vague, and rightly so. This post is my attempt to be fair, objective, and, by consequence, unrelentingly negative about Rails :)

    Edit: this post is getting more attention that I was expecting – great! However, people are not parsing the argument on HN (shocking!), so I will lay it out more succinctly.

    • Do you need performance? If so, don’t use Rails.
    • You don’t need performance. Do you need to maintain this software long-term? If so, don’t use Rails.
    • You don’t need performance and you don’t need to maintain your software. Node.js and Django offer comparable benefits to Rails, yet they have favorable performance profiles. Start there.

    Well-Intentioned Developer: “I need to develop a webapp and/or a REST API, and everyone and their dog seems to use Rails. I should, too, right?"

    No; Rails is fundamentally – and catastrophically – slow.

    This well-known set of webapp benchmarks shows that, for a single-database-query workload, Rails offers less than 1/20th the throughput of, say, Go, 25 times the average latency of Go, and more than 6 times the latency variance of Go. And Go isn’t even the most responsive or highest-throughput of the available options. The story is even more alarming for more elemental workloads that put more of a focus on the framework internals.

    And it’s no wonder. Until Rails 4, the core framework didn’t enable concurrent request handling by default. And even in Rails 4, concurrent request handling is multiplexed on a single CPU core, leaving Rails unable to take advantage of the parallelism of modern architectures. Don’t mistake concurrency for parallelism: any web framework that cannot take advantage of multiple CPU cores will suffer greatly from a throughput standpoint.

    The way to make proper use of a modern multi-core server in Rails is to run a single instance of Rails on each CPU core. Then one factors any large caches out of those Rails processes (via memcached or similar) and – ideally – places them on the same machine in order to make proper use of local memory. (That said, it seems that most people run the cache servers “wherever", which is obviously problematic from a latency perspective)

    Compare that to a system design where the web framework can use all available CPU cores and use a single in-memory cache; latency is now reduced to the time it takes to grab a read lock and fetch from main memory. It’s also a simpler programming model since there are no potential cache-fetch RPC failures to contend with.

    Well-Intentioned Developer: “Huh. Well, I am more interested in time-to-market than serving latency, and dynamic languages (and DSLs in those languages) allow me to work more rapidly."

    If you never write bugs or refactor your code, you’re probably right. Writing code in Ruby and Python and Javascript is fun; sometimes, magically so. Especially when complex ideas can be compressed into a single list comprehension or lambda application.

    However, modern dynamic languages (and their incapacity to do the sort of meaningful pre-runtime verification of basic semantic well-being one expects from a compiler) place a burden on test coverage. Of course it is essential in any language to provide test coverage for core algorithms and other subtle aspects of a software module. However, when trying to “move fast" and get to market quickly, one shouldn’t have to write tests for every souped-up accessor method or trivial transformation. In a dynamic language, if you don’t actually have test coverage for every line, you’ll inevitable run into trouble with “types and typos." Either because, e.g., you thought you were accepting a list of strings, but some caller accidentally passes in a single string without the []s, or because you fat-fingered a variable name in a rarely-taken conditional branch, or because you were expecting a duck but got a chicken. Aside from not making these [natural] mistakes in the first place, the only cure in modern dynamic languages is utterly comprehensive testing.

    In Rails, you are spending much of your dev time writing tests for things a compiler would check for you, xor you are dealing with a long-term maintenance nightmare.

    Well-Intentioned Developer: “well, you could say the same thing about Node.js, Django, or any other framework built on a modern dynamic language. I love dynamic languages, and I am willing to accept the dev cost for the tests (or the maintenance costs for the lack of tests)."

    Okay, fine. You still shouldn’t be using Rails. Ignoring the general points about maintenance of software written in dynamic languages, you’d be better of with Node.js or Django (or numerous other possibilities). They have both supported concurrent request handling for a while. As such, the communities around those frameworks have written libraries which also work well in a concurrent environment. Node.js is even designed to discourage blocking calls in general, and – thanks to that design decision and the attention paid to javascript runtime performance – it does about as much with a single CPU core as one could hope for in a dynamic language. (ed: okay, okay, HN: Node.js is not fully baked yet. It must be admitted!)

    Furthermore, the tools available for profiling Ruby are either wildly inaccurate or have such a profound effect on performance as to be misleading. And trying to make software efficient without a profiler is foolish.

    Well-Intentioned Developer: “But hiring is so difficult already, and most of the developers I encounter are familiar with Rails. Aren’t people the thing we should optimize for?"

    A great engineer will have no trouble learning a new framework. In fact, a great engineer will be excited to learn a new framework. And you should only ever hire great engineers.

    Well-Intentioned Developer: “When would Rails be appropriate, then?"

    If you already know how to get things done in Rails, you’re in a hurry, you don’t need to maintain what you’re building, and performance is not a concern, it might be a good choice. Otherwise, never.

本文固定链接: https://calc100.cn/safe/?p=26 | 百算安全平台

该日志由 百算 于2013年08月07日发表在 安全资讯 分类下, 你可以发表评论,并在保留原文地址及作者的情况下引用到你的网站或博客。
原创文章转载请注明: Why Nobody Should Use Rails For Anything, Ever | 百算安全平台

Why Nobody Should Use Rails For Anything, Ever:等您坐沙发呢!