Manish Shivanandhan Machine learning, cybersecurity, & AWS professional manishshiva.com

Comparing Elixir with Rust and Go

5 min read 1443

Comparing Elixir with Rust and Go

Programming has always been about getting things done quickly and efficiently. New developers usually start writing code with languages like JavaScript or Python, which are languages with brilliant features to build large-scale applications.

But, as your application grows, scalability, concurrency, and fault tolerance become as crucial as application features. Any company with a reasonable number of customers will have more than one language stack because some languages handle specific tasks better than others. This is where languages like Elixir, Rust, and Go come into the picture.

In the battle of system programming languages, Elixir, Rust, and Go stand out as the top three options for developers. In this article, we will look at Elixir and briefly compare its performance against Go and Rust.

Jump ahead:

What is Erlang?

Before we dive into Elixir, let’s quickly look at what Erlang is.

Erlang was created in the 1980s to solve the problem of reliable phone switching. Its name derives from the Ericsson Language because it was created at the Ericsson Computer Science Laboratory to build the next generation of telephonic switches.

Erlang offers features for creating highly scalable and concurrent code, along with impressive uptime and fault tolerance. An added advantage of Erlang is the BEAM virtual machine, a fast compiler that compiles Erlang code into bytecode.

What is Elixir?

Elixir is a functional and concurrent programming language built on top of Erlang. Like Erlang, Elixir works using the BEAM VM. This enables higher extensibility and productivity in the Erlang VM while remaining compatible with Erlang’s ecosystem.

Creator Jose Valim designed Elixir to be a highly concurrent and low-latency language capable of handling large volumes of data. Elixir also uses some of the best features of Ruby, especially its syntactic similarity.

Elixir belongs to the category of message-passing languages. Unlike most languages that call functions directly to execute an action, message-passing languages determine their action based on the message they receive. For example, they can generate an invoice when an order is received.

In the age of microservice architectures, languages like Elixir offer tools to build concurrent applications that work together seamlessly. Now that you understand what Elixir is, let’s see what Elixir can and can’t do.

Pros of using Elixir

Concurrency and scalability

Concurrency and scalability are the core philosophies of Elixir. Concurrency is the ability to run multiple processes simultaneously but independently. This is achieved by using the Erlang VM.

Elixir’s concurrency model is based on Actors. In a distributed architecture, an Actor is a process that communicates with other processes purely via messaging. Concurrency, combined with the message-passing architecture, makes Elixir an excellent choice for building distributed applications.

Scalability is also built natively into Elixir. Since applications built in Elixir are groups of individual isolated processes, all information between them is passed via messages. This makes Elixir applications highly scalable. If you need more resources for a function, all you need to do is make copies of the existing function, and add them to the application.

Fault-tolerance

Elixir programs are designed to theoretically run forever. As a developer, you understand the difficulty in writing and maintaining code. Maintaining a system with many moving parts is more challenging, especially in a distributed architecture.

Elixir uses the Supervisor and Application model to build fault-tolerant systems. In Elixir, you will have a top-level supervisor process that starts other processes in the application. Those child processes can have more supervisors and their own child processes. This recursive structure is also called the supervision tree.

The supervisor of any process can restart all the failed children. In addition, the supervisor can fail if it wants to, delegating decision-making to the supervisor above it. This Supervisor and Application model of processes is the core reason behind Elixir’s fault tolerance.

Easier learning curve

Elixir has an easier learning curve compared to languages like Rust and Go. This is due to Elixir being syntactically similar to Ruby. Elixir was also designed to be easier to adopt, unlike Erlang, which comes with a steep learning curve.

An easier learning curve helps build Elixir teams and train in-house personnel. This is also seen in the growing community support for Elixir, despite being a relatively new language on the block.



Elixir cons

Dynamically typed

While Rust and Go are statically typed languages, Elixir is dynamically typed. The difference is simple: you must compile your program before executing it in Rust and Go. This leads to slower compilation times compared to Elixir. However, this means that Rust and Go can outperform Elixir regarding speed and memory consumption.

Functional language

Elixir is a purely functional programming language. Go and Rust offer object orientation, making it easier to build complex classes. However, this is by design. Elixir is used to build a collection of distributed processes that communicate with each other, so classes and objects are overkill for a language like Elixir.

Limited community support

Elixir is a relatively new programming language, so finding developers and support might be challenging. Development teams usually choose languages like Elixir for specific use cases, so the Elixir community still has work to do to get it to the list of most used programming languages.

Who uses Elixir?

  • Adobe: Uses Elixir to build a client/cloud application for a seamless and collaborative photography workflow
  • Discord: Uses Elixir for their large-scale messaging, managing millions of concurrent users
  • Motorola: Uses Erlang and Elixir for mission-critical communication systems that need to be reliable and fault-tolerant

Comparing Elixir with Go: Speed, scale, and security

Go is a statically typed and compiled programming language. Go has been steadily gaining popularity as a systems programming language and is one of the few supported languages for writing AWS lambda functions:

  • Speed: Because Go is a compiled language, it offers better performance in terms of speed. Compiled programs are always better in speed but come with a tradeoff in developer time
  • Scale: Elixir is a better choice if your primary concern is scaling. Go offers scalability, but Elixir is far ahead in terms of scaling an application from the ground up
  • Security: Go offers memory safety features, but Elixir has better memory safety since it works only with a message-passing architecture. Since Elixir processes can only share memory and cannot call each other directly, Elixir scores better in security compared to Go

Comparing Elixir with Rust :  Speed, scale, and security

Rust is one of the most loved programming languages in the developer community. The major selling points of Rust are speed and memory safety. If you’d like to read more about Rust, check out my article on Rust iterators and closures:

  • Speed: Since Rust is also a compiled language like Go, it offers better performance in terms of speed
  • Scale: Elixir is easier to scale, thanks to its built-in concurrency and fault-tolerance design. The supervisor model also makes Elixir programs easier to build distributed applications. Rust offers concurrency as well, but Elixir performs better in distributed architectures
  • Security: Guaranteed memory safety is the primary reason developers choose Rust. Because variables and memory are tightly controlled, Rust offers better security than Elixir applications

Benchmarks in Elixir, Rust, and Go performances

Let’s look at some benchmarks in performance between Elixir, Go, and Rust. We will look at the performance of these languages by running two programs  — a "Hello, World!" function and a spectral normalization function.

The function prints the text "Hello, world!" on the screen, while the spectral norm function calculates the maximum singular value of a matrix.

Hello, World!: Elixir vs. Go vs. Rust

  +-----------+--------------------+-----------------+------------+
  |   Metric  |       Elixir       |       Go        |   Rust     |
  +-----------+--------------------+-----------------+------------+
  |  Time     | 212 ms             | 1.7 ms          | 1.6 ms     |
  |  Memory   | 45.5 MB            | 2.0 MB          | 0.6 MB     |
  +-----------+--------------------+-----------------+------------+

Spectral norm: Elixir vs. Go vs. Rust

  +-----------+--------------------+-----------------+------------+
  |   Metric  |       Elixir       |       Go        |   Rust     |
  +-----------+--------------------+-----------------+------------+
  |  Time     | timeout            | 4892 ms         | 1058 ms    |
  |  Memory   | 0.0 MB             | 5.5 MB          | 2.6 MB     |
  +-----------+--------------------+-----------------+------------+

As you can see, Rust vastly outperforms Go and Elixir. Elixir also times out when running computationally intensive operations like spectral norm, so it’s not a great choice for complex algorithms like neural networks.

Summary

Despite being a relatively new programming language, Elixir has many practical applications. Distributed systems, including blockchains and IoT services, can utilize Elixir to build reliable and fault-tolerant architectures. With growing community support and an easier learning curve, Elixir is an excellent language to invest your time on.

LogRocket: Full visibility into production Rust apps

Debugging Rust applications can be difficult, especially when users experience issues that are difficult to reproduce. If you’re interested in monitoring and tracking performance of your Rust apps, automatically surfacing errors, and tracking slow network requests and load time, try LogRocket.

LogRocket is like a DVR for web and mobile apps, recording literally everything that happens on your Rust app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app’s performance, reporting metrics like client CPU load, client memory usage, and more.

Modernize how you debug your Rust apps — .

Manish Shivanandhan Machine learning, cybersecurity, & AWS professional manishshiva.com

3 Replies to “Comparing Elixir with Rust and Go”

  1. How can you honestly say that Elixir has a lower learning curve than Go?
    Also, how is a Hello World a useful benchmark in any way? Those numbers mean nothing. What would’ve been useful is a highly concurrent use case where elixirs processes could be compared to Goroutines and whatever Rust has.

  2. Strange Comparing Elixir with Rust and Go. Yep. Go and Rust faster than Elixir. Yep. Size of application on Rust and Go is smaller than Elixir. But Elixir provide REPL for production application. Go and Rust? Nope. And you can debug and recompile modules with this REPL on fly in production. Go and Rust? I think more correct comparing is with Ruby and Python.

  3. Have you heard of the Enduro/X Middleware, which gives C/C++/Java/Go and Python the same properties as the Elixir? Middleware allows the configure and start the language agnostic binaries in several copies (even in hundreds of them), load balances the calls between them, uses message passing interface for the calls, provides fault tolerance and scaling to the multi-machine cluster. The function/service call between two binaries running typically takes about 12 microseconds. For all of the supported languages middleware provides common API for service call data parameter/buffer handling. At the core of the middleware, Unix in-memory kernel queues are utilized.

Leave a Reply