Putting them in a module in any file (with e.g. a `.ex` or `.exs` extension) and running them from there will work. You might also like to look into libraries such as `Benchee` which make benchmarking easier and prevent some of the pitfalls which a homebrew benchmarking implementation might have.

Hope this helps, and happy old year/new year :-),

~Marten

On 31-12-2021 01:01, Paul Alexander wrote:
Sorry. Would putting them in a test case be better practice? If not, do you mind telling me of the correct way which would produce the most indicative results?

On Thursday, December 30, 2021 at 6:24:08 PM UTC-5 José Valim wrote:

    Don’t benchmark in the shell. Code in the shell is evaluated and
    not compiled.

    On Fri, Dec 31, 2021 at 00:14 Paul Alexander
    <paul.aj...@gmail.com> wrote:

        Thanks for offering your opinion, José. I very much understand
        where you're coming in regards to using Enum.reduce/3 for such
        an operation, but I have found it to cause a fair amount of
        needless overhead especially when there are other operations
        going on and the updating should be the most trivial. Since
        you brought up the efficiency tradeoffs, I've put together a
        few simple benchmarks below for the Map functions where the
        results are from averaging 10k iterations. As you can see the
        performance improvement is quite drastic, with both *_many
        functions being 130%+ .

        iex> map

        %{a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10}

        iex> kv

        [a: 11, d: 22, g: 33, j: 44]

        iex> keys

        [:a, :d, :g, :j]

        iex(32)> Benchmark.measure(10_000, "reduce + replace!", fn ->
        Enum.reduce(kv, map, fn {k, v}, acc -> Map.replace!(acc, k, v)
        end) end)

        reduce + replace! avg: 18.2396

        iex(33)> Benchmark.measure(10_000, "replace_many", fn ->
        Map.replace_many(map, kv) end)

        replace_many avg: 1.0979

        iex(34)> Benchmark.measure(10_000, "reduce + update!", fn ->
        Enum.reduce(keys, map, fn k, acc -> Map.update!(acc, k,
        &(&1*2)) end) end)

        reduce + update! avg: 48.284

        iex(35)> Benchmark.measure(10_000, "update_many", fn ->
        Map.update_many(map, keys, &(&1*2)) end)

        update_many avg: 9.8719

        On Thursday, December 30, 2021 at 5:13:10 PM UTC-5 José Valim
        wrote:

            Hi Paul,

            Thanks for the proposal. My personal take is that a
            Enum.reduce/3 + the relevant Map operation should be the
            way to go, because this can easily lead to a combination
            of replace_many, update_many, put_new_many, etc.
            Especially because the many operations likely wouldn't be
            any more efficient than the Enum.reduce/3 call.


            On Thu, Dec 30, 2021 at 10:42 PM Paul Alexander
            <paul.aj...@gmail.com> wrote:

                Hi everyone,

                I would like to discuss the possibility of adding two
                new functions to each of the Map and Keyword modules;
                replace_many/2 and update_many/3. Their purpose is to
                update maps and keyword lists providing either a
                keyword list of the key-value pairs which need to
                updated, or a list of keys and a function which
                operates on the existing values of those keys.

                Far too often I find myself needing to call replace!/3
                or update!/3 several times from within a pipeline, or
                even needing to use a for-comprehension or
                Enum.reduce/3 to update a map in "one shot", when it
                feels like there should be a function for this.

                There are a number of reasons as to why I think these
                functions should be considered, but I'll provide only
                two for now:

                 1. There is already a way of updating multiple
                    key-value pairs simultaneously for maps using
                    %{map | k1 => v1, k2 => v2}. But this
                    unfortunately does not support passing a literal
                    keyword list after the cons operator.
                      * My first instinct was to see if I could expand
                        the special update syntax to handle keyword
                        lists, but I wasn't able to find where it is
                        in the codebase. If someone could point that
                        out for me because I'd like to learn how it
                        works, I'd greatly appreciate it.
                 2. It would be somewhat analogous to
                    Kernel.struct!/2, where keyword lists can be
                    passed as the second argument to update several
                    fields within a struct. Seeing as how structs are
                    maps, it only makes sense there should be a way
                    that maps could be updated in a similar manner
                    from within the Map module.


                I have already implemented the four functions,
                complete with docs, examples, and passing tests. But I
                wanted confirmation from the core team if a PR is
                welcome for this addition. Any opinions?

-- 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-co...@googlegroups.com.
                To view this discussion on the web visit
                
https://groups.google.com/d/msgid/elixir-lang-core/7c79a2b8-3a3c-48f9-a4d0-7d2e07c851e4n%40googlegroups.com
                
<https://groups.google.com/d/msgid/elixir-lang-core/7c79a2b8-3a3c-48f9-a4d0-7d2e07c851e4n%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-co...@googlegroups.com.

        To view this discussion on the web visit
        
https://groups.google.com/d/msgid/elixir-lang-core/63cf4231-5747-4f8e-99f7-87a68a7ab664n%40googlegroups.com
        
<https://groups.google.com/d/msgid/elixir-lang-core/63cf4231-5747-4f8e-99f7-87a68a7ab664n%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/cb88ccf3-ece7-47b5-a6d6-7ba5253482bfn%40googlegroups.com <https://groups.google.com/d/msgid/elixir-lang-core/cb88ccf3-ece7-47b5-a6d6-7ba5253482bfn%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/d97da267-161b-7164-c5f7-aa3453beffce%40resilia.nl.

Attachment: OpenPGP_signature
Description: OpenPGP digital signature

Reply via email to