Live data from Hacker News

Unpacking Elixir: Concurrency

underjord.io

11–20 of 138 posts

Re: Unpacking Elixir: Concurrency

#12
The deal-breaker for me with Elixir has always been the lack of real Elixir vectors rather than the crappy Erlang array library. Yes, I know you can use a Map with numeric keys but that's not the same.

Re: Unpacking Elixir: Concurrency

#13
post #3

I think a few code example would have been nice. The thing I like about concurrency in Elixir is that it's there if you need it but it's mostly not mandatory in your code, compared to Javascript where its kind of imposed on you even when it's an hindrance. I remember one trick I used to do with LiveView on click events etc was to put all async (or "asyncable") code in a spawn function, which would speed up the return…

Yes exactly! This is super important for people new to elixir. The vast majority of the time, you don't even need to know that there is even any concurrency. You can write entire sophisticated Phoenix apps and never need it. But when you do eventually need it, it's there and it's wonderful, once you grok the pattern.

Re: Unpacking Elixir: Concurrency

#14
post #12

The deal-breaker for me with Elixir has always been the lack of real Elixir vectors rather than the crappy Erlang array library. Yes, I know you can use a Map with numeric keys but that's not the same.

What would be the difference between a "real vector" and a Map with numeric keys?

Re: Unpacking Elixir: Concurrency

#16
> If I do want to do concurrent work there is the usual async/await mechanisms, implemented in the Task module. Not as weird as in JS. They just return a Task reference which is a helpful abstraction on top of the Process ID or PID. Then you can await on it to get a result or await on multiple to get multiple results. There is also a wicked function called Task.async_stream which will take an enumerable (list, map, stream or similar) and run a Task for each entry as a lazy stream. By default it has a concurrency matching the number of available cores (just like the schedulers). This is essentially a fancy shortcut for using all your machine has to offer in the service of getting the work done for tasks that are embarrassingly concurrent. It is very fun to use when bodging together scripts that you want to go fast.

Hmm, am I reading about Elixir or C#... ;-)

Yes, there are other major differences but this entire paragraph can be taken verbatim for C#.

Re: Unpacking Elixir: Concurrency

#17

Unlike javascript, elixir makes you write synchronous code, e.g. def process_items(items) do items |> Task.async_stream(&Processor.process/1, max_concurrency: 2, timeout: 7000, on_timeout: :kill_task) |> Enum.to_list() end Semantics of regular and concurrent code is the same

This. I don't want to be in an event loop by default.

Re: Unpacking Elixir: Concurrency

#18
post #16

> If I do want to do concurrent work there is the usual async/await mechanisms, implemented in the Task module. Not as weird as in JS. They just return a Task reference which is a helpful abstraction on top of the Process ID or PID. Then you can await on it to get a result or await on multiple to get multiple results. There is also a wicked function called Task.async_stream which will take an enumerable (list, map, s…

Yeah, the API is very similar.

I don't know the .Net runtime well enough to say anything about how it actually executes though.

Re: Unpacking Elixir: Concurrency

#19
Thanks for the article. I haven't written much Erlang.

I am looking for a better representation of concurrency and in my thinking I've found that it feels easier to understand is a timeline grid with rows for independent processeses and columns for time with demarcations for events. You could say a sequence diagram is closest but I'm also thinking of Chrome developer tools with its renderings for rendering, painting, javascript etc.

http://bloom-lang.net/ solves the nonorderly concurrency problems between machines with lattices.

I am unsatisfied how concurrency is represented in the mainstream languages. I find Rust async hard to understand and read at a high level from a schedule perspective. The function colouring issue is painful.

I want an interactive programming environment that lets me create a "tcp-connection" for instance and then register handlers for "on-ready-for-reading" and "on-ready-for-writing" which are system events that are triggered from IO threads that run epoll or liburing. You don't want to block the IO thread loop so you dispatch an event to another thread.

I've been designing a syntax for representing state machines and events that can be fired from different places, it looks like this:

   initialstate = state1 | state1a state1b state1c | state2a state2b state2d | state3
It waits for initialstate to be reached, then waits for state1 then it waits for state1a state1b state1c in any order and so on.

Ideally we want data flow to be a tree and sprinkled with synchronization points which are barriers where independent tasks synchronizes, where we exchange tasks and data. Shared memory synchronization is great for the amount of data that can be transferred in one-go (you're not writing lots of data into a pipe as in multiprocessing or into a buffer in message passing, message passing can be O(1)) but I don't want to do it on the hot path, Amdahls law.

Another program I've written with Java runtime executes the following program:

  thread(s) = state1(yes) | send(message) | receive(message2);
  thread(r) = state1(yes) | receive(message) | send(message2);
I've been trying to design a multithreaded server architecture here https://github.com/samsquire/three-tier-multithreaded-archit...

You could implement complicated interlocking workflows with this syntax, because you just need to wait for events as defined.

LMAX Disruptor gets some good requests per second

Re: Unpacking Elixir: Concurrency

#20
post #12

The deal-breaker for me with Elixir has always been the lack of real Elixir vectors rather than the crappy Erlang array library. Yes, I know you can use a Map with numeric keys but that's not the same.

Interesting links:

- https://github.com/elixir-nx/nx

- https://github.com/elixir-explorer/explorer

Post reply on HN