earth10

earth10

Hi, I’m just starting to build a side-project with Elixir and Phoenix and doing some basic test with Elixir alone.

What strikes me is that almost every task seems several times slower programmed in Elixir than with Python or Perl. Examples are: traversing a directory and read file modification times, read a CSV file line by line and do some basic processing with them etc.

Despite this, Elixir and Phoenix show excellent performances when compared to web frameworks written in other languages.

If I understand correctly, Elixir “worse” raw computational speed is more than balanced from its superiority in concurrency. Oversimplifying: Elixir can be 10 times slower than language X but if it’s 1000 times better in concurrency, it will shine for high traffic websites.

But then Go comes into play: with excellent raw speed and excellent concurrency too, it should outperform Elixir easily. Which according to my reading doesn’t happen: it may be faster but not by the large amount I would think.

Can somebody help me to understand how it is possible? I’m not asking for low-level explanations, only some pointer for further reading. (Maybe I should just be happy with the end result but I like to understand why things work in a given way :slight_smile: )

Thanks!

Showing Posts 1 to 10

idi527

idi527

:waving_hand:

What strikes me is that almost every task seems several times slower programmed in Elixir than with Python or Perl. Examples are: traversing a directory and read file modification times, read a CSV file line by line and do some basic processing with them etc.

If possible I’d first like to take a look at your elixir code. Sometimes there are ways to improve it a bit.

frigidcode

frigidcode

Can you link to your code please?

earth10

earth10 OP

My Elixir code is surely awful since I’m new to functional programming and I understand it’s not fair to make comparison with languages I have use since ages.

Two example of Elixir code i found to perform worse than Python and Perl equivalent are these (not mine):

But my question was more generic: I think that we can assume that Elixir is not born for raw speed and that languages like Python and Perl will usually have an advantage for simple non concurrent tasks.
If it’s not the case than my question is meaningless and can safely be deleted.

frigidcode

frigidcode

I think your original statement that raw speed isn’t Elixir/Erlang’s main advantage is correct. Areas where raw computational power is required you can use a language like Rust and write a NIF so you can utilize it from the BEAM.

I would agree with that, also add in process isolation / supervisors / etc.

kokolegorille

kokolegorille

Using Enum module is eager, meaning everything is loaded into memory, it would be better to use Stream.

Meanwhile I do not understand why not use Path.wildcard()

iex> Path.wildcard("./**")
["README.md", "_build", "_build/dev", "_build/dev/lib",
 "_build/dev/lib/chess_db", "_build/dev/lib/chess_db/consolidated",
 "_build/dev/lib/chess_db/consolidated/Elixir.Collectable.beam",
...]

# lots of dir and files

And then, if You want just files…

iex> Path.wildcard("./**") |> Enum.reject(&File.dir?/1)

# or

iex> Path.wildcard("./**") |> Stream.reject(&File.dir?/1) |> Enum.take(5)
cmkarlsson

cmkarlsson

Yes, but please also not that it is generally faster than perl/python/ruby even for computational tasks. It is slow in comparison to C/Java/Go/Rust type of languages. The “erlang/elixir is slow” quote is thrown around so much that people have started believing it is slow in comparison to any language which is not true.

I don’t believe this is true. If you look at https://benchmarksgame-team.pages.debian.net/benchmarksgame/which-programs-are-fast.html for example erlang comes in somewhere in betweeen and faster than perl and python. And these are tasks which are very unsuitable to do in erlang/elixir.

Can it be slower than perl and python for specific tasks? Of course. The task may be much easier to implement in a mutable language, it may rely on highly optimized underlying code or it is actually done in C.

On the other hand: If you have a problem domain which fits erlang/elixir then it will be fast. That is also the reason go doesn’t have more of an advantage. The computational strength of the language is not as important as its concurrent primitives and handling with IO. And even if go is generally faster when it comes to handling things concurrently the gaps narrows because the “speed” of goroutines vs processes and the underlying scheduling even things out.

11
Post #6
michalmuskala

michalmuskala

Web servers are fast in Elixir because web servers don’t do anything most of the time - most of the time they are just waiting. Either for request data or for database, etc. Elixir/Erlang are excellent at finding things to do when one of the processes doesn’t do anything, which makes them generally fast at web servers.

There’s also a question of algorithms. If you use an algorithm designed with mutable data structures in mind, it will be unavoidably slower when used with immutable data structures - on the other hand, there are some algorithms designed for immutable data structures and different, more specialised structures that can shine in some cases.

Finally, there’s the matter of the VM. BEAM is just a very well implemented and a very efficient machine. The runtime system responsible for IO interaction, scheduling and similar things have been optimised over the years. Yes, it does not have a JIT, but the normal emulator is quite fast compared to other VMs. It’s also one of the few register-based VMs in the wide usage, and register VMs generally tend to be faster than the more popular and simpler stack-based VMs.

17
Post #7
earth10

earth10 OP

Thank you everybody!

It seems that while I was right in thinking that features like concurrency are much more important than raw-speed in typical Elixir use-cases, I vastly underestimated the importance of code optimization.

I will try, as an exercise, to rewrite some of the algorithms like the directory traversal example above to make them more efficient (even if in a real word application this would probably be useless).

sribe

sribe

I suspect that quote is in reaction to all the “Elixir is lightning fast” quotes, which of course are only true when comparing to slow interpreted languages, Ruby in particular. It’s not fast when compared to compiled C++/Rust/Go and Java (well, mostly). But to have the expressiveness of Ruby plus some, at a performance level solidly between Ruby & C, is an awesome win.

earth10

earth10 OP

Ok, I tried your suggestions for code optimization and other approaches to directory traversal; the fastest way to recursively walk a directory and print file names (I gave up to printing file modify dates to keep things simple) was:

defp walk(dir) do
  Enum.each(File.ls!(dir), fn file ->
    IO.puts fname = "#{dir}/#{file}"
    if File.dir?(fname), do: walk(fname)
  end)
end

walk("/path/to/dir")

I compiled it in an executable with escript and redirected output to avoid measuring terminal speed! On a directory tree with 62.000 files it takes a time variable between 8.81 and 11.17 seconds.

The same task with python required 1.10 → 1.20 seconds.

For comparison, a shell script with find and xargs took 0.73 → 0.76 seconds

I’m wondering if I’m completely missing something obvious or if my platform, FreeBSD, is the problem. I tendo to exclude the latter since I’ve never heard about issues with the Erlang/FreeBSD combination.

Where Next? Top

Trending in Questions Top

stjefim
Hello! Suppose you are building workflow (order / task / payment) processing system with the following requirements: Each workflow con...
New
jonnycharles
I’m in search of an Elixir library that offers PDF generation capabilities similar to Ruby’s Prawn. While there have been discussions abo...
New
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
roeland
Kia ora, We have been using elixir-google-api to connect to Google Drive. However, with the updates to Tesla due to CVEs this is now bro...
New
subsaharancoder
I’ve followed the Phoenix LiveView file upload code here Uploads — Phoenix LiveView v1.0.0-rc.7 and so far everything works just fine wit...
New
jaybe78
Hello, I’m developing a online persistent chat system (what’s app) like using elixir/dynamodb/aws for a mobile app(flutter). The diffic...
New
mohsen
I’m using an Umbrella project for a Phoenix application, and I want to have one Ecto Repo and one PostgreSQL database shared by all apps....
New

Other Trending Topics Top

JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
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
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve. They are GUI (Emerge) and State management (S...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews