nginx came in at 14612 requests per second, and the dynamic code under Cowboy option came in at 13336 per second.
The same server was pulling 147 requests per second for a "hello world" rails application (Unicorn, production mode). Cowboy really isn't joking when they talk about performance.
Edit: Eh, I forgot a "not" in the last sentence, which is now added.
I have no dog in this fight, but I've seen many people say that -despite the newness of the library "ecosystem"- they get an awful lot done with Elixir/Phoenix, and have a lot of fun doing it.
(Remember that Elixir is -like Erlang- a BEAM language. This means that Elixir gets the ease-of-understanding and interesting features of its syntax and has access to all Erlang software ever written. Similarly, any and all Elixir code can be called from Erlang with little trouble.)
Edit: (Also remember that the BEAM equivalent of Ruby is Elixir, and the (most popular?) BEAM equivalent of Rails is (AIUI) Phoenix. Phoenix uses Cowboy as its HTTP(S)/SPDY server.)
In fact I recommend it for a lot of cases. Problems that were solved years ago in Rails, like sane and default CSRF protection, are showing up in newly written PHP7 and Node applications that I'm seeing, because the things that Rails does are generally there for your own good.
I'm also aware it's not a direct comparison because Rails actually had an edge as far as its codebase.
The point I believe we can still take away from the original comment is - Cowboy is fast.
I'm very much looking forward to v2, the way it handles parameters is a much more natural fit imo.
Elixir and Phoenix give you the great productivity and the performance of being run on the Erlang VM.
RoR is productive for website/web apps.
I mean looking at just request per sec that metric would be much better for something like API/data serving app.
Performance might not be on the top list, but when it comes usually a full re-write might be the only way out, as it was on our case.
Depending on the overall business situation such re-rewrite can have a huge impact on the company, due to shift on the development resources.
Since then, I only advice languages that have either JIT or AOT compilers available to them.
But in reality we need a better benchmark than "hello world". Something like TodoMVC, but for server-side development.
eg.
GET /todos
* authenticated
* 100 todos
* + threaded comments
implement the same in Rails, Phoenix, Express, and use that as a benchmark.(edited for formatting)
So if you read this Loïc, thank you for all your work and for sharing it with the community.
Our company has been sponsoring Cowboy development for about 18 months (https://medium.com/@abs/what-we-learned-from-sponsoring-an-o...)
Join us, if you can.
It seems a lot of people are having success with Erlang but I can't figure out how these applications actually run; it almost seems like there isn't a single step-by-step tutorial on the Internet for setting up an Erlang system using "best practices."
Am I just missing something? Because I feel like I'm hugely missing out.
$ mix phoenix.new my_app
which then sets up the directory structure for you to just run $ mix phoenix.server
and have cowboy serving your webapp. The guides then tell you which files to add new routes, controllers, models, etc (in a way similar to Django or Rails). All that said, it's in Elixir at that point, but maybe you could still infer how the applications and gen servers and whatnot are structured from it.It may be worth asking josevalim and chrismccord in #elixir-lang for tips on setting it up, since they obviously must know how to set up cowboy pretty well to build a system on top of it.
I think Erlang and things like cowboy and OTP are absolutely amazing for the web, but Elixir has made things 100x easier to get up and running with them.
You can also clone the repo and checkout the examples:
Make sure you have erlang installed
$ cd examples/hello_world
$ make
$ ./_rel/hello_world_example/bin/hello_world_example start
OR
$ ./_rel/hello_world_example/bin/hello_world_example console
then visit localhost:8080As someone who's been down this road in the past, unless you're already rather familiar with Erlang and OTP's conventions, the gap between the User's Guide and the API documentation is far too large to make connecting information you learn from one with information you learn from the other easy.
I've summarized my personal struggle with the Cowboy user's guide and documentation in my other comment in the thread. Please read that comment before you downvote this one. :)
It walks through a simple "Hello world" application starting with creation from template (erlang.mk), and discusses static files, SSL, websocket.. A very good first guide in my opinion. Though it doesn't really cover other techniques like how to architect your application or interact with a database.
Several months later, with a lot of additional Erlang experience under my belt, I come back to the documentation, and it's -somehow- 60->70% comprehensible. I figured out what was wrong with my simple HTTP server. (I was calling my request handler in init, rather than returning {ok, Req, []}, and letting Cowboy call my request handler later.) I still can't get cowboy_rest to work, but (OTOH) I haven't spent more than five minutes trying to get it to work since my first attempt way back when.
I don't know how much experience you have with Erlang, so I'll give you some basic advice that might be entirely unhelpful. Feel free to ask additional questions. Also feel free to ask questions on the erlang-questions mailing list. [0] Everyone who regularly posts there is very helpful. Many (most?) of them use Erlang professionally.
Anyway. Advice:
Projects/frameworks like OTP and Cowboy provide a callback API that application code is expected to conform to. Cowboy's documentation for this API is kind of all over the place, [1] but OTP's is well organized. [2]
Because Erlang tries to eschew global state as much as it can, OTP has a convention that one of the values in the tuple returned from an callback is the state for that particular instance of your application code. This State variable seems to always be the last element in the returned tuple, and the last argument to your callback function. State can be any Erlang term; it only has meaning to your application code. If your callbacks don't care about state, then you can pass anything as state. Many other frameworks have adopted this convention; it's a pretty good one.
Cowboy appears to be a pretty good HTTP/SPDY server. The beginner's documentation needs a LOT of love. (Even now, I had difficulty trying to piece together that walk through the docs in the footnote.) Given that it's a one-man shop, it's surprising that the docs are in as good a shape as they are; documentation isn't easy. :) But, still...
Anyway, questions? Comments? Ask away either here, or on the erlang-questions mailing list. :)
[0] http://erlang.org/mailman/listinfo/erlang-questions
[1] First you have to read the examples shipped with the source code https://github.com/ninenines/cowboy/blob/1.0.x/examples/hell... https://github.com/ninenines/cowboy/blob/1.0.x/examples/hell... to kind of get the impression that you need to use the cowboy_http_handler API (kinda introduced here http://ninenines.eu/docs/en/cowboy/1.0/guide/http_handlers/ and documented here http://ninenines.eu/docs/en/cowboy/1.0/manual/cowboy_http_ha... ) in order to handle plain HTTP requests. If there's a better way to arrive at this conclusion, I overlooked it. :(
[2] For example, the docs for OTP's application API: http://www.erlang.org/doc/man/application.html or the gen_server API: http://www.erlang.org/doc/man/gen_server.html The parts before the "CALLBACK FUNCTIONS" section are functions you use to manipulate an application or gen_server. The bits after are functions you implement in your module that the application or gen_server machinery will call.
I also got started from the cowboy user guide (with prior Erlang experience), but found it relatively easier, as I used the template, then cross-referenced the idiomatic template with the docs as I worked through them (tweaking 'knobs' as I went along), which worked well in helping me understand the design.
Along with the Erlang mailing list you've mentioned, I would also like to mention #ninenines (and #erlang for more general questions) on freenode. Very helpful communities!
[1] This page describes the setup: http://ninenines.eu/docs/en/cowboy/HEAD/guide/getting_starte...