First of all, Crystal is NOT, absolutely NOT parallel. It is concurrent, but not parallel. In other words it is single-core only, you will never ever get use of more that one core on a system without sharding it out like nodejs does.
So at it’s basic setup, Phoenix will run circles around Amber on multi-core systems, however Amber will be faster on single-core systems.
Rails is absolutely abysmal in my tests, summary of just raw throughput:
Ranking by Average Requests per second:
- 680446 req/sec : bin/server_cpp_evhtp
- 518792 req/sec : bin/server_nim_mofuw
- 498347 req/sec : bin/server_go_fasthttprouter
- 368537 req/sec : bin/server_rust_iron
- 337937 req/sec : bin/server_rust_nickel
- 295340 req/sec : bin/server_go_iris
- 294538 req/sec : bin/server_rust_rocket
- 261883 req/sec : bin/server_go_echo
- 241104 req/sec : bin/server_go_gorilla_mux
- 196827 req/sec : bin/server_go_gin
- 195051 req/sec : bin/server_node_clusterpolka
- 183457 req/sec : bin/server_python_sanic
- 127754 req/sec : bin/server_elixir_plug
- 119078 req/sec : bin/server_elixir_phoenix
- 111798 req/sec : bin/server_csharp_aspnetcore
- 108408 req/sec : bin/server_python_japronto
- 100829 req/sec : bin/server_node_clusterexpress
- 65878 req/sec : bin/server_crystal_router_cr
- 65102 req/sec : bin/server_crystal_raze
- 52676 req/sec : bin/server_crystal_lucky
- 48605 req/sec : bin/server_crystal_kemal
- 31704 req/sec : bin/server_nim_jester
- 23244 req/sec : bin/server_node_polka
- 11100 req/sec : bin/server_node_express
- 5661 req/sec : bin/server_ruby_roda
- 4411 req/sec : bin/server_ruby_rack-routing
- 2034 req/sec : bin/server_ruby_sinatra
- 1783 req/sec : bin/server_python_flask.py
- 722 req/sec : bin/server_python_flask
- 594 req/sec : bin/server_ruby_rails
(Amber is not in the above results because it’s code is bugged but it’s close to the other crystal frameworks).
Amber is a LOT faster than Rails on raw throughput, but as always the user code will affect a lot.
Yep, this is because Crystal the language (and thus no framework on it) is not multi-core capable.
Eh, I don’t know about Crystal, but Elixir is not a one-man project, it is backed by a company and has a lot of authors at this point (with a BDFL though), in addition, as you can see on recent stack overflow benchmarks, Elixir is one of the fastest growing languages out and already in the top 20 of server usage.
Exactly, benchmarks are not useful for showing real information at all. I think micro-benchmarks (like my above linked raw throughput testing) can be useful to show the implicit overhead, but large benchmarks are near-useless.
You can get things built yourself fast in phoenix though, while having a far far faster base speed, and being significantly easier to reason about.
Yeah, I really really don’t like the base syntax of Crystal… Even Rust does default-immutable… >.>
Do not underestimate the importance of this!!!
‘Mostly’. There’s a reason I don’t call OCaml a bare-metal-language even though it’s near C speed and compiles to direct machine code, and Crystal has the same reason, it has a GC, and unlike OCaml’s GC, Crystal’s GC is the C’based HB Collector, really basic and not terribly fast, I.E. you get ‘non-base-metal’ random costs because of collections. In addition the GC only manages memory resource, not other resources, where if the language was better designed and could manage all resources in a scoped manner (like Rust does) then it wouldn’t need a GC and it would have a unified syntax for all resources. As it stands you either have to pass callbacks (that do get inlined admittedly) and do all the work inside that (think the with
command in Python) or you have to explicitly and manually call the reclamation functions for the resource (and don’t forget that or it ‘might’ get reclaimed by the finalizer if a finalizer was made for it, and even then that will only be ‘sometime later’).
Phoenix also naturally scales across machines as well.
Crystal has Oracle IP?! o.O