Clarification on ordered for Task.async_stream

I have another question about concurrency in Elixir I hope someone can help me understand. I have been studying the Task module. I am reading the documentation for the Task.async_stream/5 https://hexdocs.pm/elixir/Task.html#async_stream/5
but I am confused by the ordered option. I think I understand what it does – if it is false then tasks a, b, and c may be returned in some different order like b, c, a.

However, I am struggling to understand these sentences: “This option is useful when you have large streams and don’t want to buffer results before they are delivered. This is also useful when you’re using the tasks for side effects.”

Is that saying that using ordered: false is useful when you have large streams? And should I use ordered: false if I am only using the task for side effects?

I think that makes sense, but I do not trust my own understanding with this yet.

Thank you for clarifying!

1 Like

I don’t know why they mention side effects in the docs. Seems to me those could be sensitive to ordering. It really all depends on your algorithm whether the order of the results is important to preserve.

If you have ordered: true but the tasks complete in order of b, a, c, then the internal logic has to buffer the result of b, wait for a to finish, send a’s result downstream, then it sends the buffered b’s response, etc.

If your algorithm can operate correctly with ordered: false I would recommend it, no matter the size of the stream or side-effects.

3 Likes

I think it could be better worded as “when you’re using tasks only for the side effects”. The ordered key will not make side effects occur in the order of the enumerable, it’ll only affect the returned stream. Side effects will always occur when the task is processed, so if you need to rely on side effect order you should use Enum.each or Enum.map. As you point out, with ordered: false, there’s no need to buffer the results. So the docs are saying basically if you’re going to pipe Task.async_stream into Enum.each, you should use ordered: false.

4 Likes

Both of your points are great, PR to the docs are appreciated. :slight_smile:

2 Likes

I’ve never had the chance to submit a pr to the docs, this seems like a great opportunity! I’ll get on that today :smile:

1 Like

PR submitted! Thanks for the encouragement :smile: https://github.com/elixir-lang/elixir/pull/10359

6 Likes