Ah, df has no effect on a JIT system, I forgot about that. Is the memory measurements guaranteed to have consistent effect of the GC across benchmarks?
On Mon, Jan 3, 2022 at 20:06 Wiebe-Marten Wijnja <w...@resilia.nl> wrote: > I have run some benchmarks (comparing OTP23 with JIT-enabled OTP24). > Full results here: https://github.com/Qqwy/elixir-test-benchmrking_then/ > > It compares, in a situation where no tail recursion optimization is > possible, `Kernel.then/2` vs. writing the same code manually vs. using > `Kernel.then/2` with `@compile :inline`. > > > A brief summary of the results: > > - OTP24 is able to get roughly twice as many iterations per second as > OTP23. However: > - On OTP24: > - using `Kernel.then/2` requires (when tail recursion is not possible) > 2.5x the memory of the other two variants. > - using `Kernel.then/2`is roughly 30% slower than the other two variants. > - On OTP23: > - all three techniques use the same amount of memory. > - using `Kernel.then/2`is roughly 8% slower than the other two variants. > > Strange... > > > I also took a look at the disassembled code using :erts_debug.df as you > suggested. > Details here: > https://github.com/Qqwy/elixir-test-benchmrking_then/#looking-at-the-disassembled-code > *(Note that under OTP24 the *.dis-files only contained 1-5 empty lines, so > the output is from OTP23. Should I file a bug with the OTP team for this?)* > > It seems that also during loading, no optimization of immediately-called > anonymous functions is taking place. > Above benchmarks seem to support this fact, although the results w.r.t. > memory usage and the difference in slowdown vs OTP23/24 seems very odd to > me. > > > How to continue? > > > ~Marten/Qqwy > On 03-01-2022 17:30, José Valim wrote: > > The optimization may happen on the loader. Use erts_debug:df(Mod, Fun, > Arity) and see that. > > On Mon, Jan 3, 2022 at 5:03 PM Wiebe-Marten Wijnja <w...@resilia.nl> wrote: > >> I've been running my tests on Elixir v1.13.1 built for OTP24 with OTP >> 24.1.2. >> When decompiling the resulting BEAM bytecode, the anonymous functions are >> still visible. >> >> I will do some benchmarks to see how the resulting performance is. Maybe >> the JIT will do something which is not visible in the BEAM bytecode. >> On 03-01-2022 16:57, José Valim wrote: >> >> then/2 is a macro and the emitted code should be optimized from >> Erlang/OTP 24+. >> >> On Mon, Jan 3, 2022 at 4:28 PM w...@resilia.nl <w...@resilia.nl> wrote: >> >>> Since v1.12 we have the macro `Kernel.then(value, function)` which >>> expects an arity-1 function and will call it with the given value. >>> >>> This makes code which used to be written as follows: >>> >>> ``` >>> def update(params, socket) do >>> socket = >>> socket >>> |> assign(:myvar, params["myvar"]) >>> |> assign_new(:some_default, fn -> 42 end) >>> >>> {:noreply, socket} >>> end >>> ``` >>> >>> more readable, by allowing it to be written as: >>> >>> ``` >>> def update(params, socket) do >>> socket >>> |> assign(:myvar, params["myvar"]) >>> |> assign_new(:some_default, fn -> 42 end) >>> |> then(&{:noreply, &1}) >>> end >>> ``` >>> >>> This pattern seems to be common in codebases using Elixir 1.12 and up >>> (At least according to anecdotal evidence). >>> >>> All is well. Except there is a little snag: The new code does not have >>> the same runtime characteristics (both in performance and in memory usage) >>> as `then`desugars to `(function).(value)`: An anonymous function is created >>> and immediately run (and then garbage collected soon after). >>> >>> The Erlang compiler is clever enough to optimize these >>> immediately-called anonymous functions away, but it will only do so when >>> `@compile :inline` is set in the given module, to not mess with the call >>> stack that might be returned when an exception is thrown. >>> >>> Now `@compile :inline` is quite the sledgehammer, as it will inline >>> *all* functions in the current module (as long as they are not 'too >>> big', which can also be configured, and only in the places where they are >>> called statically). >>> But since we're dealing with anonymous functions here which do not have >>> clear names, there is no way to predict the name one should pass to the >>> `@compile` option. >>> >>> >>> It seems like this situation could be improved, although I am not sure >>> how. >>> >>> Is there a way to mark these anonymous functions in some kind of way, to >>> allow only them to be inlined? >>> Or is there maybe a way to have the Elixir-compiler already inline >>> common patterns like a capture with a datatype, rather than relying on the >>> Erlang compiler for this? >>> Your input is greatly appreciated. >>> >>> ~Marten/Qqwy >>> -- >>> You received this message because you are subscribed to the Google >>> Groups "elixir-lang-core" group. >>> To unsubscribe from this group and stop receiving emails from it, send >>> an email to elixir-lang-core+unsubscr...@googlegroups.com. >>> To view this discussion on the web visit >>> https://groups.google.com/d/msgid/elixir-lang-core/f0da2df2-432e-423c-a02b-27d8b916a0ecn%40googlegroups.com >>> <https://groups.google.com/d/msgid/elixir-lang-core/f0da2df2-432e-423c-a02b-27d8b916a0ecn%40googlegroups.com?utm_medium=email&utm_source=footer> >>> . >>> >> -- >> You received this message because you are subscribed to the Google Groups >> "elixir-lang-core" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to elixir-lang-core+unsubscr...@googlegroups.com. >> To view this discussion on the web visit >> https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4%2Bu8RTb8sMAJyGiuw6%2BgGgyuVZVxjpFad9M%2BbEgYrwkbg%40mail.gmail.com >> <https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4%2Bu8RTb8sMAJyGiuw6%2BgGgyuVZVxjpFad9M%2BbEgYrwkbg%40mail.gmail.com?utm_medium=email&utm_source=footer> >> . >> >> -- >> You received this message because you are subscribed to the Google Groups >> "elixir-lang-core" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to elixir-lang-core+unsubscr...@googlegroups.com. >> To view this discussion on the web visit >> https://groups.google.com/d/msgid/elixir-lang-core/b02049e0-8d86-a7b4-e8e0-396bb9ecd4f0%40resilia.nl >> <https://groups.google.com/d/msgid/elixir-lang-core/b02049e0-8d86-a7b4-e8e0-396bb9ecd4f0%40resilia.nl?utm_medium=email&utm_source=footer> >> . > > >> -- > You received this message because you are subscribed to the Google Groups > "elixir-lang-core" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to elixir-lang-core+unsubscr...@googlegroups.com. > To view this discussion on the web visit > https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4KqHRqTEisWYLNi7n2UQzP5XtVMUYkLbkHyiVyjcvKFOg%40mail.gmail.com > <https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4KqHRqTEisWYLNi7n2UQzP5XtVMUYkLbkHyiVyjcvKFOg%40mail.gmail.com?utm_medium=email&utm_source=footer> > . > > -- > You received this message because you are subscribed to the Google Groups > "elixir-lang-core" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to elixir-lang-core+unsubscr...@googlegroups.com. > To view this discussion on the web visit > https://groups.google.com/d/msgid/elixir-lang-core/84dbf8a8-4f9f-5aa7-efc3-1658e097a8c5%40resilia.nl > <https://groups.google.com/d/msgid/elixir-lang-core/84dbf8a8-4f9f-5aa7-efc3-1658e097a8c5%40resilia.nl?utm_medium=email&utm_source=footer> > . > -- You received this message because you are subscribed to the Google Groups "elixir-lang-core" group. To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-core+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4Jod05LOG61Wf08gkNR0FTSDx8W4gWSZdr96k7BZ94UrQ%40mail.gmail.com.