Qqwy

Qqwy

TypeCheck Core Team

Enum fusion?

Hi all!

As you may know, it is very common in idiomatic Elixir code to work with transformations on datastructures, especially those implementing the Enumerable protocol. Usually we use the functions from Enum (and sometimes from Stream) to manipulate these, often in a pipeline of multiple steps.

Since the Enumerable protocol is an implementation of the Foldable concept from category theory, whose main fundamental operation is reduce(in other languages also known as ‘fold’), which always outputs a list, we end up using lists virtually everywhere.

This means that in an Enum pipeline, a lot of intermediate lists are being generated. I seem to remember José explaining on the mailinglist back in the day(note: I was unable to find it; if you know where this was mentioned, let me know and I’ll link to it!) that Enum’s functions were intentionally not implemented as macros to make it easier to follow stack traces when something broke.

I think this is definitely the right choice, especially since a lot of Elixir code is written with “IO-bound” operations in mind, in which sheer computing speed is less important.

However, it did start making me wonder: What about creating a FastEnum drop-in replacement, where map, reduce, etc. would be implemented as macros that would fuse consecutive operations together to improve performance?
In many cases, a pipeline of Enum-functions could be transformed into a single for-comprehension. Besides the added benefit of fusing consecutive calls, for is also extremely well optimized by the BEAM.

Now, why did I start this topic? I essentially have two questions/topics for discussion:

  • Do you think a library like this would be worthwhile?
  • Do you happen to know whether someone already performed any exploratory work in this direction? (The ideas presented here are, after all, far from novel.)

First Post!

ityonemo

ityonemo

Are you encountering a speed bottleneck somewhere?

Most Liked

sasajuric

sasajuric

Author of Elixir In Action

I think this is a very interesting idea which is worth giving a shot. In the worst case scenario you’ll bump into some hard limitations, but even then something good can come of it, for example a blog post which documents the experiment, explains why it failed, and presents the existing options (like for and plain recursion).

I can see this being useful when I want to quickly see what would be the effect of fusing a couple of Enum operations. Presently this requires a more complex rewrite, while FastEnum could turn this into a simple search & replace. I actually had the need for something like this on a couple of occasions (I think it was mostly AoC challenges). I’m not sure I’d use FastEnum in the final version though. Most probably I’d turn the hot pipeline into a plain recursion, which should be the fastest option.

sabiwara

sabiwara

Elixir Core Team

Hi all!

I remember reading this thread a while ago, but I had no idea how one would implement such a macro back then. The idea resurfaced lately as I was finding myself rewriting some bottleneck Enum code as specialized recursive functions to speed it up. Out of curiosity, I started to play with the idea of a defenum macro to automate the process.

The result looks quite promising in terms of performance / flexibility, although this is still highly experimental dark magic at this stage :slight_smile:
I published the POC to get some feedback, let me know your thoughts!

https://github.com/sabiwara/enumancer

NobbZ

NobbZ

That’s not quite the same.

The benefit of proper fusion is to get the memory characteristics of the Stream (which avoids building and intermediate lists) while retaining the speed of a regular Enum.

In combination a fused Enum is therefore faster in theory as it avoids allocations and takes stress from the GC.

Last Post!

hst337

hst337

If you’re interested, we can collaborate on enum optimizations in optimizing compiler I am writing.

Some optimizations are just not possible with regular approach and they require proper call stack analysis for purity and safeness of some calls. For example,

list
|> Enum.map(f1)
|> Enum.map(f2)

Can be joined into one Enum.map only when f1 is pure.

Plus some Stream calls can be translated to Enum calls, and Enum calls can be translated to :lists calls, which can then be inlined.

PM me if you’re interested

Where Next?

Popular in Discussions Top

CharlesO
Erlang :list.nth simple, but 1 - based nth(1, [H|_]) -> H; nth(N, [_|T]) when N > 1 -> nth(N - 1, T). Elixir Enum.at … coo...
New
ben-pr-p
In general I’ve been sticking to this community style guide GitHub - christopheradams/elixir_style_guide: A community driven style guide ...
New
rower687
Hi all, I’ve been reading a lot about the “let it crash” term and how supervising processes and the whole messaging passing make an elixi...
New
tmbb
This is a post to discuss the new Phoenix LiveView functionality. From Chris’s talk, it appears that they generate all HTML on the serve...
342 18595 126
New
AstonJ
Seen any cool LiveView demos, sample apps or examples? Please post them here! :003:
New
Fl4m3Ph03n1x
Background A few days ago I was listening to The future of Elixir from Elixir Talks, with Dave Thomas (@pragdave ) and Brian Mitchell. I...
New
AngeloChecked
What learn first? Rust or Elixir Hi Elixir community! I’m here because i want learn a new language. I’m a junior developer and mainly i ...
New

Other popular topics Top

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
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers’ Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
New
dokuzbir
I want to highlight html closing tags when i click a html tag. That works in .html files but doesnt work for html.eex templates. How can...
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
sergio
Kind of like when jquery came out, it was super necessary. Existing drag and drop libraries have a bunch of baggage to support old browse...
New

We're in Beta

About us Mission Statement