Given two large and different maps defined as follows
Interactive Elixir (1.9.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> m1 = Map.new(1..1_000_000 |> Enum.map(&{&1, &1})); :ok
:ok
iex(2)> m2 = Map.new(2..1_000_000 |> Enum.map(&{&1, &1})); :ok
:ok
it takes a significant time difference when comparing them using ==/2
and Map.equal?/2
iex(3)> :timer.tc(fn -> m1 == m2 end)
{21, false}
iex(4)> :timer.tc(fn -> Map.equal?(m1, m2) end)
{20487, false}
What is the reason of this time difference between ==/2
and Map.equal?/2
, and which to use?
Equivalently, which to use between ==/2
and ===/2
? (because Map.equal?/2
calls to ===/2
, see here)
Thanks
Indeed, Map.equal?/2
is simply delegating to Kernel.===/2
.
Kernel.===/2
is delegating to :erlang."=:="/2
and Kernel.==/2
is delegating to :erlang."=="/2
. The latter compares numbers while the former compares values and types.
Consider the following example.
%{1 => 1} == %{1 => 1.0}
#⇒ true
%{1 => 1} === %{1 => 1.0}
#⇒ false
That said, Kernel.===/2
should compare all the values. OTOH, Erlang/OTP reference explicitly states that
Maps are ordered by size, two maps with the same size are compared by keys in ascending term order and then by values in key order. In maps, key order integers types are considered less than floats types.
If it was indeed true, two maps of the different size, as in your example, should have returned in the nearly same time.
The summing up, I would consider this time difference to be a bug in :erlang."=:="/2
implementation, worth to report to Erlang team.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With