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.mans...@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-core+unsubscr...@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/CAGnRm4KURBq00_fVUtQ7zSsOVswEWKaLo%3DnZ6ufrtbyM3HaByg%40mail.gmail.com.