Hotelicopter also runs on Clojure. And I would recommend Colin Steele's description of his decisions as CTO, as he took the codebase away from PHP, first to Ruby and then to Clojure. The bit about the failures of Ruby are (in my opinion) the most interesting. Basically, it was too much work to get Ruby to go fast enough, and their problems were solved by using Agents in Clojure.
This I think is the key bit of the story:
"At this point, we were still focused on using Ruby/Eventmachine as a cornerstone of our technology stack. But here we hit a snag. Yep. I’m gonna beat up Ruby, because it was a mistake.
...it doesn’t scale. ::ducks::
OK, that’s not completely fair. Ruby does scale. But it doesn’t scale well, or easily, and in benchmarking and stress testing, I was seeing that we were going to have a use a small truck load of resources at AWS, or spend a bunch of preciousssss developer time making it scale. It was too expensive. I wanted high user::machine density, and I didn’t want to have my developers do handstands to get it.
Yeah, I could’ve done lots of things. I didn’t have time to do that shit. Not with a four person team. Not with cash running out, and promises to keep, and no time to work for Ruby. I needed something that would work for me. This thing had to be FAST. It had to drive hardware to the limit without driving us crazy.
The bottom line is that it was too much work to make Ruby go fast enough.
...A little background on our application might help. Our job is to give prospective hotel bookers a view into what their options are. At the time we were making the decision to migrate from Ruby to Clojure, the system was using so-called “realtime” rates and availability checks with hotel suppliers to get that information. That meant that when a visitor conducted a search, we would spin up dozens of individual HTTP requests to hotel supplier sites to get rates and availability data at that very moment. We’d parse the responses, collate them, and present them back to the UI in just a few seconds.
You might ask why we didn’t cache that information, but suffice it to say there were significant business drivers for that decision.
Managing this concurrent (and long-running) IO was a major theme for us, and Ruby did so reasonably well using EventMachine. However, we had to normalize the returned data into a single unified data model, and none of our partners had simple (or compact) XML representations of the data, so not only did we have IO issues, but CPU-bound processing issues as well. The combination of the two made the EventMachine implementation suffer from less-then-stellar throughput, and because of Ruby’s green threads implementation and global interpreter lock, we had to run oodles of Ruby processes on each box to achieve reasonable throughput.
Perhaps just as importantly, the reactor pattern’s upside-down flow of control style of programming was (and is) a pain in the ass. It was hard to read, hard to maintain, and generally obstreperous.
..I can already year you Ruby folks protesting “Fibers!” and so on. Heh. Have fun storming that castle.
Clojure was a whole different story, and addressed these issues admirably, for all the reasons you’ll discover when you look into it further. "
From this description it seems that Erlang/OTP would be even better choice than Clojure: we literally pack million of concurrect users into 1 high memory AWS instance.
Though Erlang not as modern or elegant as Clojure, but there is also LFE and Joxa.
It depends on how many external libraries you need. We considered both Clojure and Erlang in our project, ended up going with Clojure mostly because of available and easily accessible Java libraries.
I still find it amazing that I can:
1) add a single line to my project.clj (which will set up dependencies and download libs),
2) add a single line to my :import section at the top of the source file,
3) there is no point 3. Just call Java libraries.
But the choice really depends on your application.
Leiningen probably has its root from Maven, which IMHO the killer tool for Java. I've done .NET, a bit of Python, and RoR development/toying/experimentation in the past, and you need Bundler+Rake+RubyGem (at least) to emulate the core (important) feature of Maven.
Noticing that languages built on the Erlang VM seem to be more along the lines of "an X-like on the Erlang VM" instead of "X on the Erlang VM" (like JRuby, IronPython, ClojureScript). Is Erlang's VM less adaptable to existing languages vs. the JVM, etc.?
That's part of it, but it's also just that there's little motivation for using it as a general-purpose VM. Building a precise clone of Python on the Erlang VM would be more difficult than on JVM, but more importantly, it would be pointless — Python does not have the kind of deep-rooted concurrency semantics that are Erlang's raison d'etre. If you try to stick an existing language that doesn't closely resemble Erlang on the Erlang VM, all you're doing is creating a really awkward implementation of that language and not really gaining anything. So you end up with languages that are similar to X but with a huge transfusion of Erlang's semantics so that they're useful.
The default implementations of scripting languages do not scale, unless we making use of the advanced VMs or JIT techniques of alternative implementations.
A startup I was part of, made this discovery already back in 2002, when we moved our scripting based web framework, which was very much like Rails, but based on Apache/TCL, to the then early .NET beta.
This I think is the key bit of the story:
"At this point, we were still focused on using Ruby/Eventmachine as a cornerstone of our technology stack. But here we hit a snag. Yep. I’m gonna beat up Ruby, because it was a mistake.
...it doesn’t scale. ::ducks::
OK, that’s not completely fair. Ruby does scale. But it doesn’t scale well, or easily, and in benchmarking and stress testing, I was seeing that we were going to have a use a small truck load of resources at AWS, or spend a bunch of preciousssss developer time making it scale. It was too expensive. I wanted high user::machine density, and I didn’t want to have my developers do handstands to get it.
Yeah, I could’ve done lots of things. I didn’t have time to do that shit. Not with a four person team. Not with cash running out, and promises to keep, and no time to work for Ruby. I needed something that would work for me. This thing had to be FAST. It had to drive hardware to the limit without driving us crazy.
The bottom line is that it was too much work to make Ruby go fast enough.
...A little background on our application might help. Our job is to give prospective hotel bookers a view into what their options are. At the time we were making the decision to migrate from Ruby to Clojure, the system was using so-called “realtime” rates and availability checks with hotel suppliers to get that information. That meant that when a visitor conducted a search, we would spin up dozens of individual HTTP requests to hotel supplier sites to get rates and availability data at that very moment. We’d parse the responses, collate them, and present them back to the UI in just a few seconds.
You might ask why we didn’t cache that information, but suffice it to say there were significant business drivers for that decision.
Managing this concurrent (and long-running) IO was a major theme for us, and Ruby did so reasonably well using EventMachine. However, we had to normalize the returned data into a single unified data model, and none of our partners had simple (or compact) XML representations of the data, so not only did we have IO issues, but CPU-bound processing issues as well. The combination of the two made the EventMachine implementation suffer from less-then-stellar throughput, and because of Ruby’s green threads implementation and global interpreter lock, we had to run oodles of Ruby processes on each box to achieve reasonable throughput.
Perhaps just as importantly, the reactor pattern’s upside-down flow of control style of programming was (and is) a pain in the ass. It was hard to read, hard to maintain, and generally obstreperous.
..I can already year you Ruby folks protesting “Fibers!” and so on. Heh. Have fun storming that castle.
Clojure was a whole different story, and addressed these issues admirably, for all the reasons you’ll discover when you look into it further. "
http://www.colinsteele.org/post/23103789647/against-the-grai...