ydg33

ydg33

Why is &__MODULE__.local/n faster than &local/n?

I noticed that if I pass a captured function (e.g. &logger/4) as an argument to :telemetry.attach/4, I get a warning:

[info] The function passed as a handler with ID “…” is a local function.
This means that it is either an anonymous function or a capture of a function without a module specified. That may cause a performance penalty when calling that handler. For more details see the note in telemetry:attach/4 documentation.
telemetry — telemetry v1.2.1

… but if I change this to &__MODULE__.logger/4, I no longer get that warning. The link says:

Note: due to how anonymous functions are implemented in the Erlang VM, it is best to use function captures (i.e. fun mod:fun/4 in Erlang or &Mod.fun/4 in Elixir) as event handlers to achieve maximum performance. In other words, avoid using literal anonymous functions (fun(...) -> ... end or fn ... -> ... end) or local function captures (fun handle_event/4 or &handle_event/4 ) as event handlers.

Is there more documentation about what “due to how anonymous functions are implemented in the Erlang VM” is alluding to? I read the documentation for &/1 but it doesn’t go into detail about why &foo/n is different from &__MODULE__.foo/n, and I am curious!

The Erlang documentation on functions makes it sound like foo() and m:foo() should have the same performance (Functions — Erlang System Documentation v27.0):

This is a rough hierarchy of the performance of the different types of function calls:

  • Calls to local or external functions (foo(), m:foo()) are the fastest calls.
  • Calling or applying a fun (Fun(), apply(Fun, [])) is just a little slower than external calls.
  • Applying an exported function (Mod:Name(), apply(Mod, Name, [])) where the number of arguments is known at compile time is next.
  • Applying an exported function (apply(Mod, Name, Args)) where the number of arguments is not known at compile time is the least efficient.

Are local function captures (without the module name) compiled into Erlang Fun()s instead of local/external functions? If so, why?

Marked As Solved

ydg33

ydg33

So others can actually find the answer through search & don’t have to click through:

The difference comes into play with code loading. The local captures will reference the version of the module they were captured with, while remote/external captures will always reference the latest version of the module.

From: https://groups.google.com/g/elixir-lang-core/c/rW_BRCULsGk/m/3hYXyye6AAAJ

Made a rough draft of a change to the documentation here: Clarify what specifying the module name does with & by jyc · Pull Request #13668 · elixir-lang/elixir · GitHub

Also Liked

sabiwara

sabiwara

Elixir Core Team

You might want to check these similar threads about this topic:

There is a proposal discussing this as well:
https://groups.google.com/g/elixir-lang-core/c/rW_BRCULsGk/m/9rrYEwwtAwAJ

Where Next?

Popular in Questions Top

logicmason
Hi there, I'm working through my first release with elixir/phoenix. I've built a release with distillery and found that it crashes when I...
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
Kagamiiiii
Student & New to elixir. Nice language. I want to convert a english character, e.g. “a”, which is stored in a variable, to it’s asci...
New
script
If I have a string “1000 cfu/ml” . I want to remove the characters and / and space . So the string is like this "1000" What is the ...
New
Phillipp
Hey, I have a NanoPi-M3 and try to install Elixir on their Ubuntu image. I followed the Raspberry Pi installation instructions from the ...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
chewm
Hi guys, nice to meet you to the whole forum, I’m new here, I’m trying to configure visual studio code for elixir, right now the intellis...
New
sabri
Can someone explain the settings of pool_size of Ecto in config file? and what is the recommend size? Thanks
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New

Other popular topics Top

freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
yurko
Here are few pieces of (common) Linux knowledge that we use for reasonably small one server apps. We use Ubuntu but this should work for ...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
grych
Hi folks, Few months ago I have announced the proof-of-concept of the library to manipulate the browsers DOM objects directly from Elixi...
639 49522 488
New
malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
lk-geimfari
What is most correct way to open, read and parse JSON file with poison? For example if we have example.json file in root of some projec...
New
danschultzer
None of the current solutions worked well for me, so I went ahead and built a user management system from scratch. This project took far...
548 27727 240
New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New

We're in Beta

About us Mission Statement