josefrichter

josefrichter

Hi guys,

I came across this table from Sasa Juric’s book summarizing which common components of a (ruby) web app can be replaced with Erlang

Chris McCord mentioned in his ElixirConf 2017 Closing Keynote that it’s rather difficult for experienced Elixir devs to see the Elixir world through the eyes of newcomers again, so here we go :slight_smile:

For a newcomer (from Ruby world) like me, it would be quite helpful to get a bit more detail about which specific parts of the Elixir ecosystem replace those components. There’s a lot of new terms like GenServer, Supervisors, ETS, Mnesia, etc. etc. that don’t ring any bell for a newcomer, so such a mental map could fix that.

To be more specific, these are some of the questions I’m trying to find answers for:
– what do I use instead of Redis and why?
– what do I use instead of Sidekiq and why?
– how does Erlang ecosystem render some components, that are common in Ruby world, unneeded?
– how does the whole ‘concurrency’ promise help me deal with the fact that at some point all the concurrent connections might need to write into a database at once?
– what are some BAD use cases for Erlang/Elixir, where I’m better off sticking with Ruby?
– etc.

Thank you very much!

Showing Posts 1 to 10

wmnnd

wmnnd

Hey there and welcome!

Saša’s list is, of course, a little tongue-in-cheek but ultimately true.

Let’s look at some of the points from the list:

  1. HTTP Server: You don’t need to use a third-party public-facing HTTP server because the solutions written in Erlang (like Cowboy) are ready to handle this already.
  2. Redis/Sidekiq: You don’t need to use third-party software for handling background data processing or in-memory caching since this can all easily be achieved with Elixir/Erlang processes.
  3. It’s kind of a running joke in the community to ask whether you even need an external database. Theoretically, you could also use Erlang’s in-memory database ETS and occasionally save it to your hard disk. But many people like to use SQL or noSQL database and they work just fine with Elixir/Erlang.

Regarding the advantages of concurrency when you eventually still end up writing to a database: Well, not every HTTP request needs to write something to a database and even then, you profit from increased stability, responsiveness and availability of your sever if it is able to handle concurrency better :slight_smile:

I can’t really think of use-cases in which you’d want to go with Ruby over Elixir/Erlang. There are, however, cases in which you might want to go with a language that compiles to native code (like C/C++/Rust) instead in order to get some performance benefits.

There are some nice introduction books and courses for Elixir out there. I have personally read »Programming Elixir« and it covers many important aspects of both the language and Erlang/OTP.

I can also recommend this little video series about GenServer and Supervisors on YouTube if you want to get a quick fix:

kokolegorille

kokolegorille

ETS Erlang Term Storage

– what do I use instead of Sidekiq and why?

Background processes is easy as spawning a process, usually a GenServer

– how does Erlang ecosystem render some components, that are common in Ruby world, unneeded?

Which components?

– how does the whole ‘concurrency’ promise help me deal with the fact that at some point all the concurrent connections might need to write into a database at once?

When having a limited resource and lots of requests, You can use poolboy, like Ecto does for db access

– what are some BAD use cases for Erlang/Elixir, where I’m better off sticking with Ruby?

Often, people coming from Rails complain for not having devise out of the box. I am also coming from Rails, and what I miss the most is a plugin called awesome nested set to manage db tree.

Maybe the gem world is still bigger than hex world. But Elixir gains so much from Erlang/OTP that I would not consider reusing Rails vs Phoenix.

kokolegorille

kokolegorille

I forgot to mention

service crash recovery

But that is so obviously Elixir/Erlang strong point, where You can recover any processes with the help of supervision tree.

orestis

orestis

I’ve never used Ruby, but at least from a Python perspective, the main difference between Elixir/BEAM and those languages is that the BEAM VM is designed to be effectively started once and never restarted, and it can use all the cores of a machine without needing to spawn new OS-level processes to maintain responsiveness.

So, the main mental leap you have to do is:

Trust the VM: It will not crash, it will not leak memory, it will not block.

hubertlepicki

hubertlepicki

ETS, DETS, Mnesia. Or Redis. Nothing stops you from using Redis.

Maybe nothing. Maybe you just spawn a process/task and it does some job. Or maybe you use one of the libraries for background jobs.

I do not think it does. It makes building certain things on your own easier, however. Think bout background jobs queue, that you might not need to build or use because you’re good with async tasks that you can just crate ad hoc.

In my experience (>10 years writing Ruby code), this problem occurs when you have many connections that are open to database… while most of them are doing nothing. Ruby is using the database connections very inefficiently. Starting a request will open connection, where you can open transaction, then do some Ruby computations, then write something, then at the end it closes the connection etc. Elixir’s default DB library for many - Ecto - does use connection only when it needs to write/read some stuff, and then immediately checks it out to the pool. The 2nd thing is that explicit need to preload sutff when you make query makes it easier to reduce the N+1 queries your app does. So it’s using the DB more efficiently.

If you really have multiple writes from multiple threads/workers then you’re toast either way :smiley:

When you have limited budget and there’s plenty of components you can glue together Ruby app from that are out there already. Especially true if you are just starting up with Elixir. In general, Elixir app will take slightly more effort and slightly more code than similar Ruby/Rails app.

AstonJ

AstonJ

I would probably use Elixir’s Task - it’s built in and lets your start a process in the background extremely easily :003:

Tasks are processes meant to execute one particular action throughout their lifetime, often with little or no communication with other processes. The most common use case for tasks is to convert sequential code into concurrent code by computing a value asynchronously

NobbZ

NobbZ

In general I’d sign, but you still can produce huge space-leaks easily.

When you read a full GiB file into memory in raw binary mode, it will be allocated in the bin_heap. When you now simply do the following:

def foo(<<c :: binary-size(1), _ :: binary>>), do: foo(c)
def foo(<<c :: binary-size(1)>>), do foo(c)

This will not only loop forever, but keep a reference to the original binary, therefore it can’t get garbage collected ever.

This leak can be avoided by doing as follows:

def foo(<<c :: binary-size(1), _ :: binary>>), do: c |> :binary.copy |> foo
def foo(<<c :: binary-size(1)>>), do foo(c)

This will enforce copying the subbinary and therefore not keep a reference to the original binary, therefore it can be garbage collected.

In erlang this produced many shooting holes in my feet :wink:

orestis

orestis

Fair enough. My point though was more about memory leaks you cannot reasonably fix yourself, rather than memory leaks that happen in code you directly control.

OvermindDL1

OvermindDL1

@Nobbz that is not a ‘leak’ though, it is still pointed to and referenced. A leak is something that is dereferenced but never released, meaning that it can never ever again be reclaimed, that is definitely not your example. ^.^

michalmuskala

michalmuskala

The described situation is no longer true in OTP 20. The GC will copy small fragments of big binaries (under 64 bytes) directly to the process heap, instead. This does not solve all the problems but does reduce the issue significantly.

Where Next? Top

Trending in Questions Top

Blokh
Hey guys, I’ve got a huge CSV ( around 10 GB ) that needs to be processed hourly Do you guys have any suggestions what is the best prac...
New
kszambelanczyk
Hello! Could someone please give me a help/sample code, how to delete a file from s3 using waffle/waffle_ecto from Phoenix app. I creat...
New
Onor.io
I have what I’ve heard referred to as a “lookup table” in my database. This is a way of assigning codes to common values. One common lo...
New
Trolleger
What approach to take when sending live updates to “random” users Hi! I have a question, I have a little chat app, and when I create a DM...
New
matt-savvy
Anyone here using Honeybadger? My Honeybadger account is being overwhelmed with noise from some bots. Seeing a lot of Bandit.HTTPError...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge &amp; Solve. They are GUI (Emerge) and State management (S...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
wintermeyer
There are three potential reasons for members of this forum to have a look at https://vutuv.de You are tired or annoyed of LinkedIn. Yo...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews