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 intelemetry:attach/4documentation.
telemetry — telemetry v1.4.2
… 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/4in Erlang or&Mod.fun/4in Elixir) as event handlers to achieve maximum performance. In other words, avoid using literal anonymous functions (fun(...) -> ... endorfn ... -> ... end) or local function captures (fun handle_event/4or&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 v29.0.2):
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
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: https://github.com/elixir-lang/elixir/pull/13668
Also Liked
sabiwara
You might want to check these similar threads about this topic:
There is a proposal discussing this as well:
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance









