📜 ⬆️ ⬇️

When did Phoenix kill Reils?


It happens that some problems can not be solved in your usual programming language. Suppose we were faced with the task of implementing real-time messaging with large volumes of traffic. How to make it optimal? For obvious reasons, Ruby is not the best option for this, so you have to start searching for alternatives. Many ways will appear before you, and as for a rubist, the best choice would be to use Elixir.


Elixir is a functional programming language with Ruby syntax, working on the Erlang virtual machine. Therefore, for a person from Ruby’s world, familiarity with the language will be very easy. Although in order to understand it completely, you will have to try, repeatedly re-reading the documentation .


The answer to the question from the title and the mass of interesting about Elixir immediately under the cut.


Never! Phoenix is ​​not a killer Rails, but a partner


The structure of the web application on both platforms is quite similar. And this is not surprising: one of the most significant members of the Phoenix community is a former member of the core team Reils, and most people involved in the development of the framework are rubists. Some differences still exist.



There is also a huge number of small differences, ranging from the built-in tools for working with the front-end, ending with ideas and philosophy different from Rails.


Erlang's virtual machine and what it eats


Ruby is an object-oriented programming language. It is an interpreted language created by Yukihiro Matsumoto with a view to productivity and simplicity. The elixir is a functional language created by José Walim and running on an Erlang virtual machine called BEAM . Programs are compiled into a bytecode for BEAM , which looks like a single process of the operating system, but in fact harbors the whole universe.


BEAM runs on the server continuously. The Ruby process (and Rails) is started only when the server starts processing the request. Therefore, if, for example, you need to perform some kind of action every hour, in the Reils environment you will have to use CronJob , while in Phoenix a little Elixir-program inside BEAM will take care of this.


 defmodule Stack do use GenServer # Callbacks def handle_call(:pop, _from, [h | t]) do {:reply, h, t} end def handle_cast({:push, item}, state) do {:noreply, [item | state]} end end # Start the server {:ok, pid} = GenServer.start_link(Stack, [:hello]) # This is the client GenServer.call(pid, :pop) #=> :hello GenServer.cast(pid, {:push, :world}) #=> :ok GenServer.call(pid, :pop) #=> :world 

In the Elixir to perform the task, there is the possibility to create a new process (which in the magical world of Erlang behaves more like a thread, although in fact it is neither the one nor the other), while in Ruby most of them have to put background tasks in a separate queue (for example , via Sidekiq ) so that you can scale independently of the web application.


Since the processes are isolated, and when exchanging messages, a new copy of the data is created, you no longer have to worry about data damage or changes on the other side of the system. The operations within the process are synchronous, so the order of its execution is much more adequate than in the same Node. Another advantage is an efficient garbage collector. Once the process has “worked its way,” it frees the memory for the OS.


Ruby streams ( JRuby , Rubinius ) tend to interact with data from other streams, which is then quite problematic to debug. In such cases, the race condition develops fairly quickly.


Work with web sockets


Real-time applications (for example, chat rooms) use a data exchange channel (for example, a web socket). Creating such using the Phoenix - easy. With Rails, this is also possible, but the ActionCable component, which serves connections to web sockets, will hardly cope with the first thousand simultaneous connections. From the point of view of Phoenix, the ActionCable algorithm for sending messages from the server to the client is ridiculously simple, unreliable, and poorly scalable. So that you understand how advantageous to use in this case, the Elixir and Phoenix: the application can easily handle a couple of hundred thousand simultaneous connections from one server.


To be fair, if you run into problems with the Rails cable on a running application, I advise you AnyCable , one of the implementations of which is made right on Erlang. Thereby you will get the benefits of BEAM on the Rail application.


Running large-scale web applications with BEAM especially enjoyable: scaling to multiple servers is very easy. Creating a project in Phoenix, you can forget about the problems with scaling. By the way about this ... You know that the WhatsApp server also works on BEAM ?


~~~


Many frankly declare that in order to make the application scalable, it is necessary to use the Elixir, because Ruby and Rails are not capable of it.


This is extremely short-sighted advice, showing that its author is not entirely familiar with the concept of scaling. Let Ruby is not the smartest programming language, but you can scale a typical Rails application without much effort. Such an application is usually based on an architecture without resource sharing, which in most cases allows increasing the total number of processed requests per second by simply adding servers.


Maybe not the cheapest option in terms of iron, but exactly scalable!


~~~


Functional programming vs OOP


Sometimes the Elixir is slightly reminiscent of Ruby. This is significantly confusing, because Ruby belongs to the world of object-oriented programming, and the Elixir is built on the principles of the functional. These are two parallel universes! If you and Ruby have long since switched to “you,” it will still take time to understand Elixir.


Phoenix - this is not just a nimble Rails, written on Elixir


Let's look at what is the process of sending messages in the Elixir, using the following module:


 defmodule Example do def start_link do spawn(fn() -> loop() end) end def loop do receive do {:hello, pid} -> IO.inspect("Got hello from #{inspect pid}") end loop() end end 

And now let's open IEx :


 iex(1)> pid = Example.start_link() #PID<0.120.0> iex(2)> send pid, {:hello, self()} "Got hello from "#PID<0.118.0>" "#PID<0.118.0>" {:hello, #PID<0.118.0>} 

Looks like OOP, isn't it? In the Erlang / Elixir community, even with humor, they note that these two languages ​​correspond more closely to OOP concepts than other popular programming languages. So, Elixir is an object-oriented language? Nothing like this. But more on that later.


The advantages of messaging are that the sender is known in advance, and the interaction of the processes can be controlled. Visualization and debugging processes become much simpler compared to what happens with the usual methods of controlling parallel threads, such as locks and mutexes.


Unlike object Ruby, a code on a functional Elixir consists of modules, each of which includes a set of functions, usually aimed at solving a particular type of problem. A huge plus of the Elixir is that the results of certain actions are predictable.


Arguments of each function are written in advance, which saves the developer from further difficulties, for example, with instance variables. It also helps to avoid the above problem, when some part of the system interacts with data not intended for it.


Competitiveness


About Ruby, you can say that his competitiveness is lame. Yes, in some versions of Ruby stream concurrency is supported, but the built-in MRI (the original Ruby written in C language) method of synchronizing GIL streams prevents competitive execution of tasks. It should be noted that Ruby still allows competitive input-output operations.


The elixir is simply made for this. Literally. Competition in it is realized on the basis of the so-called “model of actors” - a concept implemented by the Erlang virtual machine even before this term saw the light.


The idea is that you can create isolated processes that interact with each other through the exchange of messages and do not affect the states of each other. An example of such a model you saw in the previous section.


It should be noted that rubists like the Elixir usually have no less than Ruby himself once liked. The problem here can be switching from one language to another. Each of them is good and attractive in its own way, but it is impossible to write simultaneously in two languages. We'll have to make a choice.


Work with databases


Let's compare the most popular tools for working with databases in Ruby and Elixir, respectively - ActiveRecord and Ecto . Both allow you to make requests and use validations, but they still function completely differently. For rubists, ActiveRecord is simple and easy to use; moreover, it does not require any knowledge of SQL . The story with Ecto completely opposite: it is more difficult to understand, plus you need a basic knowledge of SQL .


 defmodule Sample.App do import Ecto.Query alias Sample.Weather alias Sample.Repo def keyword_query do query = from w in Weather, where: w.prcp > 0 or is_nil(w.prcp), select: w Repo.all(query) end def pipe_query do Weather |> where(city: "KrakĂłw") |> order_by(:temp_lo) |> limit(10) |> Repo.all end end 

It can be said that ActiveRecord is the secret weapon of the Rails ( from which everyone really turned up their nose ). About Ecto this can not be said. Ecto is good, but Phoenix is ​​on top without him, but Rails would not be himself without ActiveRecord .


Gems vs packages


A heme is a code created by another developer that can be easily integrated into your application. Essentially a regular library. Most of the rubists in their projects constantly use the same set of gems. It can be said that the code without gems is like food without salt. To appreciate the full power of the geme ecosystem, take a look here .


In the world of Elixir, such pieces of software from third-party developers are called packages. The ecosystem of packages has not yet grown to the scale of the gems ecosystem (for more details , click here ). Judging from the way Phoenix and Ecto , packages should not create problems with updates in the future. But you can say for sure only a couple of years later.


Speed


It's safe to say: Phoenix is ​​faster. Much faster than Rails.

')

In the open spaces of the network you can find a lot of information about various performance tests, detailed and not so much. It's funny, but when you try to load test and "overload" the server with the Elixir, the testing machine will rather fail, even despite the excellent performance indicators.


And the speed of development in Ruby and Elixir (as well as on the Rails and Phoenix) takes approximately the same time. Of course, moving from one framework to another for the first time, you need to understand that the loss of time is inevitable.


Fast deployment without downtime


For most web applications, little downtime when updating software doesn’t cause any problems. Many companies are trying to eliminate a 1-2 minute downtime without even realizing that they are throwing money down the drain. Although in some cases, deployment without downtime is really necessary.


We'll have to sweat to solve this problem in Ruby's environment, and the Elixir will cope with it with a bang: BEAM has built-in functionality for this purpose - hot-swappable code. For many, it becomes a miracle. Here are just the most likely have to abandon the Docker. In short, some advantages.


But do not be in a hurry to rejoice: if the update includes a database migration, it will not be so easy to achieve a lack of downtime for both technologies.


Yukihiro vs Jose David vs chris


Yukihiro Matsumoto and José Valim are really significant people, each of whom has done a lot for their language and community as a whole. But let's now talk more about the creators of the driving forces of each of the languages. Open source projects such as Rails and Phoenix, as a rule, have large development teams. In such teams, product creators usually play a key role. They determine the direction of development and conduct public activities.


Creator Rails David Heinemeyer Hensson aka DHH has been giving presentations since the very first day of his brainchild. He is a great speaker. Earlier, his talks at RailsConf conferences always opened their eyes to many things. Now he has lost a little position, but his contribution is still enormous.


David is able to give visibility to dry examples. In addition to programming, he is engaged in photography and motor sports. But still his ability to “revive” a software product or a book (yes, he is also a writer ) is difficult to compete with.


David may seem arrogant, but he can be understood. The Rails community is much larger than the Phoenix community, and David just physically couldn’t communicate with anyone at conferences, as Chris does.


Not that money was an indicator of success, but David became a multi-millionaire thanks to his company Basecamp working on the Ruby and Rails stack.


Chris McCord, the founder of Phoenix, also speaks publicly from the very beginning. Chris was a member of the Rails community, but somehow he didn’t find a solution to several issues and went to Elixir for the sake of it. One feels that he is no less passionate about his creation than David once was. At conferences, Chris is more loyal to newcomers; his reports are more adapted for the unprepared listener.


Chris works for DockYard , whose leader has assembled an impressive team of elixirs. The company also has a cool blog , many articles from which we translate for our site .


The main problem of both frameworks


The biggest challenge is finding good developers, which is relevant for both Phoenix and Reils. Although for the Phoenix, this task is much more acute. And this is a huge problem. Why do we need a perfect framework if there is no one to work in it? Perhaps Phoenix should be friends with first-class PHP developers?


Today everyone speaks about Elixir and everywhere. It's time to start studying it - right now.


The driving force of technology is you and me, so join the development on Elixir as soon as possible!


And which framework would you choose?


Summarizing, we can say that Phoenix offers slightly more powerful technologies, but this is not yet an indicator of the success of the project. What really matters is the presence of developers who are well versed in the framework with which they work.


If you have been driving a project on Rails for a long time, be extremely careful when switching to Phoenix. In a foreign court, the grass is always greener. In their practice there are successful transfers, but almost always they were engaged in the master of their craft.


If you already have a team of talented Rails developers who want to try something new, then you should organize some side project on Phoenix, watch what happens, and then decide whether the game is worth the candle.


Elixir and Phoenix can be used to create conventional CRUD applications if your company wants this for some reason, be it functional programming, the presence of only one server, the novelty of the language, etc.


If speed and deployment without downtime are vital to your project, then with Phoenix you are exactly on the way.


And whatever you choose, you know, there is no wrong option.


Conclusion


This article is an adaptation of the compilation of three materials:



Over the translation worked Hope / tresstensel .
Adaptation material performed Jaroslav / jarosluv .


PS All those interested are invited to the mitap on the Elixir in the Rambler on October 19 at 19:00. For residents of other cities and countries will be organized online broadcast.


PPS Answers to questions about the Elixir in Telegram .

Source: https://habr.com/ru/post/339460/


All Articles