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.

Reply via email to