I made a Phoenix webapp as a veteran Rails dev
reddit.com
reddit.com
I get the premise, just trying things and having fun. But I get the impression that in a lot (most?) scenarios this would be a lateral move at best. His last comment about going with Phoenix instead of Rails for new projects, if he's not just being kind, that seems like a major case of throwing out the baby with the bath water.
Goodbye 10 years of experience, knowledge of pitfalls, etc...hello 1 month of promise and years of gotchas and relearnings for small benefit?
And then there is survivorship bias. What if by some strange turn of events, ColdFusion had continued to evolve and eaten its respective niche? While I wouldn't condone an attitude of not being open to new things, the ColdFusion stalwarts would look like sages, while people who invested in an upstart technology could well have wasted a lot of time.
The move "backwards" to older, more mature technologies happens often enough, too. Startup uses latest NoSQL thing, and then realizes an old timey SQL database would have saved them a lot of trouble, etc. It cuts both ways.
In that case, the multithreaded nature of Elixir and the VM there's no comparison.
I tried searching for raw ruby+erlang benchmarks but couldnt find much in the short time I looked.
If we're talking about pure ruby and elixir, things become complicated, you can do some stuff a bit faster in ruby sometimes (where ruby is using native optimized C code)
DHH even acknowledges this: "But sure, I'd like free CPU cycles too. I just happen to care much more about free developer cycles and am willing to trade the former for the latter."
I still respect and use ruby/rails, but it's not my first choice anymore.
For sure its a lack of careful thinking and consideration of trade offs I'd take any issue with...it sounds like you didnt come to those conclusions out of emotion or a deep yearning for something new.
And yes, sometimes my tasks go beyond the simple CRUD, but as of today, I'd choose Phoenix anyway because I find mysef more comfortable with it rather than with Rails.
Even the fact that I can think to use a 512mb DigitalOcean droplet without fear is a plus, but not the main reason :-P
The Elixir community may be an amalgamation of Rails folks looking for better runtime performance and cool new tech, and Erlang folks looking for syntactic sugar and a growing developer community. (I'm neither.)
Elixir's author was one of Rails core contributors, which probably also helps in bringing the Rails crowd over. One could think of Elixir as a "better" version of Rails rewritten on top of the Erlang stack, even if Rails and Elixir are apples and oranges under the hood.
See also: the inverse of OP's article, the creator of Erlang trying out Elixir (2013) [1]
[1] http://joearms.github.io/2013/05/31/a-week-with-elixir.html#...
* edited for spelling
(I know it seems a pretty obvious question, but I can't find satisfactory answers that make sense to me at least.)
Coming from imperative languages especially (speaking for myself), have to re-think/re-learn how you write code, but it does end up being a worthwhile investment
Short syntax:
Enum.map [1,2,3], &(&1 * &1)
Long syntax: Enum.map [1,2,3], (fn num ->
num * num
end)
Or even: square_me = &(&1 * &1)
Enum.map [1,2,3], square_me
square_me_too = fn(num) -> num * num end
Enum.map [1,2,3], square_me_too
Defining a function separately (e.g. even in another module) and referencing it: def square(num) do
num * num
end
def doing_something() do
...
Enum.map [1,2,3], &square/1
Enum.map [1,2,3], &SomeOtherModule.square/1
...
end class Array
def square
map {|e| e * e}
end
end
Why storing code in a seperate module is a superior way than storing code in its class?Think of:
items = ["file_a", "file_b", "file_c"]
Enum.map items, &HelpfulDownloaderModule.download/1
download/1 is probably pretty complex and/or can be of use in other pieces of code.Bad oop is clearly inferior to good functional. ie React. But if OOP is able to do functional as well, shouldn't OOP win on the long run?
If you try to code functional in an OOP language, you would have to make sure that no third party modules (or coworkers accidentally) write code that "misbehaves" in such aspects. Just like you currently have to make sure that the Ruby code you use is threadsafe.
With immutability you gain all those features baked into Erlang/OTP (scalability, reliability).
`List.get_elem` you can write an higher order function `List.get_Nth_elm` which takes `List.get_elem` as an agrument .
Try to check Trailblazer for a different approach.
It sounds like this guy has sucked on the rails teet for far too long, instead of challenging himself with other approaches and paradigms.
It's still a smaller community so frameworks and such are still being developed. Currently there's a Sinatra inspired library, Kemal:
https://github.com/kemalcr/kemal
and then there's Kemalyst, which handles MVC and the like:
Rails apps can utilize all cpu cores without you doing anything special as well (Since Rails 5 its default web-server is Puma, which is multi-process and multi-threaded). I agree this fact is pretty damn awesome, but what (if any) are the significant differences between Phoenix and Rails in this respect?
At first, it sounded like you were implying (by distinguishing between the web server and 'the actual Ruby app') that Phoenix automatically parallelizes portions of an _individual_ request across multiple threads/cores using some special asynchronous dataflow-paradigm primitives or something. It would be unique and truly awesome if that were true, but I still highly doubt it.
I don't doubt that Phoenix probably delivers orders-of-magnitude better performance than Rails in many other respects, but 'utilizing all cpu cores without you doing anything special' is nothing unique to Phoenix over Rails as I understand it.
So yes, Phoenix does "automatically parallelizes portions of an _individual_ request across multiple threads/cores using some special asynchronous dataflow-paradigm primitives or something."
Edit: quoting you is not meant to be condescending... I'm not sure if it comes off that way or not.
Edit 2: Not an expert and it may not be parallelized, but portions of the requess can be doled out to other threads, and when there's any down time from IO, other requests can use the thread...
process response -> deserialize -> put/get something from the DB -> send response
However, let's say you need to send off many requests to multiple external services in order to respond to a particular request. These would be trivially parallelized in Erlang.Another thing to note is that, let's say Puma is running 8 workers and a bug crashes the app. Every client connected to that worker is going to lose its connection while that worker is restarted. In Erlang, you have one process for each client so only one client notices the crash.
And finally, the overhead of starting multiple Ruby processes (in this case OS processes) per Ruby interpreter is way, way larger than a starting multiple Erlang processes. It's a difference of 300MB vs 2KB.
I guess you're mixing up processes with Ruby threads.
You normally start as many Puma processes as your CPU/Core count with probably additional threads per workers.
Erlang, on the other hand, has a preemptive scheduler that is capable of keeping all cores hot.
But the beauty of HTTP is that you can scale simply by adding more "endpoints". That means you can add as many processes (workers) as necessary to utilize all CPUs, or even add as many servers as you can afford.
I'm not saying that Elixir does not do a better job with it's lean processes and built-in OTP stuff.
But it's not true that you can't utilize all CPUs with a Rails app.
Rails app-servers fork multiple OS processes to utilize all CPU cores despite the GIL.
If you define a 'Rails app' as a single un-forked OS process (a definition I've never heard before) then yes, tautologically, a 'Rails app' could not utilize all CPU cores because of the GIL.