Sorry, for the short replies, I was on my phone. :)

What I mean is, are the measurements across examples guaranteed to have the
same amount of garbage collector calls (or no calls at all)? I am worried
that, for quick snippets, the memory measurements are being influenced by
other factors. But according to my understanding the anonymous function
should not be allocated on Erlang/OTP 24 (and I think some further
improvements are coming on 25).

Plus comparing against OTP 23 and 24 will be tough due to the JIT.

On Mon, Jan 3, 2022 at 8:38 PM Wiebe-Marten Wijnja <w...@resilia.nl> wrote:

> Yes, across benchmark runs the memory measurements are the same.
> On 03-01-2022 20:17, José Valim wrote:
>
> 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
> <https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4Jod05LOG61Wf08gkNR0FTSDx8W4gWSZdr96k7BZ94UrQ%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/178e943c-84c3-31c4-9e41-903ad2f8da32%40resilia.nl
> <https://groups.google.com/d/msgid/elixir-lang-core/178e943c-84c3-31c4-9e41-903ad2f8da32%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/CAGnRm4LqMq6oLpncmWethkon3Xpbp%3DTQAw8kOm96sU%2Bf3qvj0Q%40mail.gmail.com.

Reply via email to