On 10/27/22 3:42 PM, José Valim wrote:
> 1. Maps are slower (significantly enough to avoid IMHO), but do give
the flexibility desired (1.79x slower, which could compound if in the
wrong place)
Do you have a source for the 1.79 slower?
I don't expect maps to be slower but, more importantly, the difference
here should be negligible because options rarely exceed more than a
dozen keys and in those scenarios lookups are in the order of
single-digit microseconds (source
<https://github.com/erlang/otp/issues/6139#issuecomment-1182995087>)
*in the worst case*. So it seems counter productive to say you
wouldn't pick the more flexible option because an operation will take
1.75us instead of 1us (assuming it is indeed slower). :)
Plus maps have other benefits such as reading multiple keys at once
which will certainly offset keyword lists.
1.79 times, as I read it, not 1.79us. And of course benchmarks being
highly subjective, now that I retooled it it's at 2.12x slower (see
notes at the very bottom for likely reasons why).
What drove me to look into this is a very specific situation we face in
my project where we process a high frequency of events on a databus per
second, and it was bogging down. As I isolated easy wins (external
database calls) I started looking into other inefficiencies.
Specifically this is a call that looks at the before and after state of
a struct and from that decides if changes should be handled or not.
I expect many will likely find fault with the implementation of this
benchmark, but it is for a specific use case... for the room in general:
let's not digress on if there are better ways to do a thing or not :)
The gist includes three scenarios:
* ordered — arguments are given in order and pipelined (this is what
we are using now)
* map_get — arguments are culled ala Map.take()
* map_pattern — arguments use a pattern match w/a dictionary
The #'s:
Name ips average deviation
median 99th %
ordered 5.06 M 197.65 ns ±21980.53% 143
ns 230 ns
map_get 3.86 M 259.27 ns ±28310.93% 183
ns 494 ns
map_pattern 2.39 M 418.72 ns ±11140.31% 426
ns 551 ns
Comparison:
ordered 5.06 M
map_get 3.86 M - 1.31x slower +61.61 ns
map_pattern 2.39 M - 2.12x slower +221.07 ns
The gist / benchmark that created the above:
https://gist.github.com/srevenant/ed28a0cf2a167379a21eb482291313ce
Why the change?
I did change it from when I ran it previously to come up with the 1.79x
number, because it was referencing our code base, and in the previous
benchmark I had less arguments it was matching against. I added a few
more arguments to amplify the situation, as you can see.
I do realize this is NOT the heart of my performance problem, so I hope
others can avoid digressing into "you should do it this other way" type
discussions :D
This is just something that came out of exploring some performance issues.
And the suggestion for efficient named arguments came because we'd
switched to ordered arguments, and then the code was flipped in one
place (a, b) vs (b, a) (face-palm)
-Brandon
--
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/f3307a40-b4fe-c66f-0576-a162202dfee2%40cold.org.