PragTob

PragTob

Blog Post: Careful what data you send or how to tank your performance with Task.async

I ran into an interesting problem recently where simple concurrency on the BEAM via Task.async made my application a lot slower and a lot more memory hungry. This blog post illustrates the issue with a short example, where processing 3 non-trivial actions on a list in parallel is slower than doing it sequentially, and then explains why this happens and what can or can’t be done about it.

Most Liked

dimitarvp

dimitarvp

Come on now. Unless you have a strict one-thread-pinned-per-core runtime then you can’t claim it for any runtime, Golang’s and Rust’s tokio’s included.

Fact is that most parallel runtimes do parallelization on a best-effort basis and they do a damn good job at it. There was a rather hilarious article a while ago reposted on HN how the Linux kernel never used more than 4 (or 8?) cores for a while, some years ago. What can a runtime do if the kernel is lying to it? But that’s a separate topic.

So… 100% guarantee? No, but it’s at least 90%.

lud

lud

No as long as you stay in the same process then you do not care, basically, as the data is not copied. The closure will use the same pointer to the data as the parent scope does.

D4no0

D4no0

Using the term parallel in this context is incorrect, the correct term would be concurrently and this has some very important implications:

  1. You are not guaranteed that the spawned tasks will be running on a separate physical core, as this is decided by the scheduler, there are ways to configure this manually, however you will be breaking the abstraction level of concurrency used in elixir and potentially introduce locks;
  2. As the scheduler switches context between running processes, every process will get a slice of execution time, naturally having more processes on the same thread will make them run slower.
dimitarvp

dimitarvp

To be fair, that wasn’t very surprising. Parallelizing in such a manner only saves time when (1) there’s lots of it (not just 3 tasks) and (2) the data is not being carried around but is crunched into much smaller pieces and/or sent off to other systems (Kafka, Postgres et. al.).

But the article was informative and interesting, and I thank you for it.

warmwaffles

warmwaffles

Unbounded parallelism is generally not a good tactic. Your workload and underlying hardware capabilities should be well understood to help determine how concurrent you want a set of tasks to go.

Where Next?

Popular in Blog Posts Top

danschultzer
How to set up the Content Security Policy header with Phoenix LiveView and support inline styles and scripts with CSP nonces.
New
elbrujohalcon
We all know about the most renowned Erlang/Elixir centers worldwide, like Sweden, Brazil, California, and London. But the community, even...
New
paulanthonywilson
https://furlough.merecomplexities.com/elixir/otp/tdd/2021/03/18/test-driving-otp-creating-a-registry-with-expiring-entries.html Followin...
New
paulanthonywilson
All a bit meta, but this is a quick post on creating a Jekyll blog post from a Livebook page. Posted via Devtalk (see this thread for ...
New
brainlid
There is a new community resource available on writing “Safe Ecto Migrations”. When we get a migration wrong, it can lock up your product...
New
brainlid
This post asks if we can remove Alpine from the PETAL stack. Can we do everything we need with just LiveView? Also, let’s explore an area...
New
paulanthonywilson
https://furlough.merecomplexities.com/elixir/otp/networking/nerves/2021/03/09/fun-with-multicasting.html Post on using UDP multicasting ...
New
AstonJ
Update: How to use the blogs section You can post in one of the Official Blog Posts threads (like this one), or, via Devtalk and a new t...
New
brainlid
Dialyzer is a tool that you’ve probably heard about in the Elixir community. You may have even used it. However, adding Dialyzer to an ex...
New
mudasobwa
Just blogged on the general approach to creating easily extendable applications with plugin support.
New

Other popular topics Top

shahryarjb
Hello, I get Persian date from my client and convert it to normal calendar like this: def jalali_string_to_miladi_english_number(persi...
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
KronicDeth
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine) This is a plugin that adds support for Elixir to JetBrains IntelliJ...
289 35421 110
New
mgjohns61585
Could someone help me? I'm making my first elixir program, number guessing game. I can't figure out how to convert the user's guess from ...
New
minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list....
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID<0.412.0> terminating ** (Postgrex.Error) FATAL...
New
beno
I will often find my self writing things similar to: case some_value do nil -> something() "" -> something() _ -> someth...
New

We're in Beta

About us Mission Statement