Set `MAP_SMALL_MAP_LIMIT` to 1 in dev/test

61 views
Skip to first unread message

Zach Daniel

unread,
Oct 28, 2022, 12:20:10 AM10/28/22
to elixir-lang-core
Myself and many other developers have been bitten by the fact that maps are sorted if they have less than 33 elements. Not because we believed that we should rely on the sort ordering of a map, but because we *accidentally* wrote an implementation that did, and didn't test it with more than 32 elements. Then at some point later in actual use things get strange, and debugging the above scenario can be very difficult (but is of course obvious in retrospect). This could be opt-in or opt-out, all the same to me, although unless the performance impacts are huge I think that it would save new developers even more time than experienced developers and so should potentially be opt-out. After a while when you start to see things "showing up in weird orders" you have an intuition to go look for a map being enumerated, but that isn't something a beginner would likely think of. 

As far as I know this is an erlang thing, but I'm not too familiar with erlang and thought I'd float it by the elixir group first. I'm also not sure if its possible to change those constants based on Mix environments (or to change them at all), but I imagine that is where it will intersect with Elixir. 

José Valim

unread,
Oct 28, 2022, 1:34:41 AM10/28/22
to elixir-l...@googlegroups.com
Can you please provide the documentation for said environment variable from Erlang?

Also note that atom keys will likely no longer be sorted alphabetically in Erlang/OTP 26, which should help with said assumptions.

On Fri, Oct 28, 2022 at 06:20 Zach Daniel <zachary....@gmail.com> wrote:
Myself and many other developers have been bitten by the fact that maps are sorted if they have less than 33 elements. Not because we believed that we should rely on the sort ordering of a map, but because we *accidentally* wrote an implementation that did, and didn't test it with more than 32 elements. Then at some point later in actual use things get strange, and debugging the above scenario can be very difficult (but is of course obvious in retrospect). This could be opt-in or opt-out, all the same to me, although unless the performance impacts are huge I think that it would save new developers even more time than experienced developers and so should potentially be opt-out. After a while when you start to see things "showing up in weird orders" you have an intuition to go look for a map being enumerated, but that isn't something a beginner would likely think of. 

As far as I know this is an erlang thing, but I'm not too familiar with erlang and thought I'd float it by the elixir group first. I'm also not sure if its possible to change those constants based on Mix environments (or to change them at all), but I imagine that is where it will intersect with Elixir. 

--
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/a528c1bb-b8e1-429c-b1ff-a98db36ee2d6n%40googlegroups.com.

Zach Daniel

unread,
Oct 28, 2022, 1:56:08 AM10/28/22
to elixir-l...@googlegroups.com
Sorry, it isn't an environment variable as far as I can tell, its just a constant in `erl_map.c`. https://github.com/erlang/otp/blob/master/erts/emulator/beam/erl_map.c

In this case I was using string keys, but reducing the likelihood of this foot gun in any way is good :)


On Fri, Oct 28, 2022 at 12:34 AM, José Valim <jose....@dashbit.co> wrote:
Can you please provide the documentation for said environment variable from Erlang?

Also note that atom keys will likely no longer be sorted alphabetically in Erlang/OTP 26, which should help with said assumptions.
On Fri, Oct 28, 2022 at 06:20 Zach Daniel <zachary.s.daniel@gmail.com> wrote:
Myself and many other developers have been bitten by the fact that maps are sorted if they have less than 33 elements. Not because we believed that we should rely on the sort ordering of a map, but because we *accidentally* wrote an implementation that did, and didn't test it with more than 32 elements. Then at some point later in actual use things get strange, and debugging the above scenario can be very difficult (but is of course obvious in retrospect). This could be opt-in or opt-out, all the same to me, although unless the performance impacts are huge I think that it would save new developers even more time than experienced developers and so should potentially be opt-out. After a while when you start to see things "showing up in weird orders" you have an intuition to go look for a map being enumerated, but that isn't something a beginner would likely think of. 

As far as I know this is an erlang thing, but I'm not too familiar with erlang and thought I'd float it by the elixir group first. I'm also not sure if its possible to change those constants based on Mix environments (or to change them at all), but I imagine that is where it will intersect with Elixir. 

--
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+unsubscribe@googlegroups.com.

--
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+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4LBVOhd3AkP70QfkO486njj02%2BXYLGoAgF5M7AeHBGGJg%40mail.gmail.com.

José Valim

unread,
Oct 28, 2022, 2:03:00 AM10/28/22
to elixir-l...@googlegroups.com
Oh, you didn’t say it was an env var either. :) I just assumed based on the casing.

In any case, that’s a C constant. It can only be changed while the VM is building.

On Fri, Oct 28, 2022 at 07:56 Zach Daniel <zachary....@gmail.com> wrote:
Sorry, it isn't an environment variable as far as I can tell, its just a constant in `erl_map.c`. https://github.com/erlang/otp/blob/master/erts/emulator/beam/erl_map.c

In this case I was using string keys, but reducing the likelihood of this foot gun in any way is good :)


On Fri, Oct 28, 2022 at 12:34 AM, José Valim <jose....@dashbit.co> wrote:
Can you please provide the documentation for said environment variable from Erlang?

Also note that atom keys will likely no longer be sorted alphabetically in Erlang/OTP 26, which should help with said assumptions.
On Fri, Oct 28, 2022 at 06:20 Zach Daniel <zachary....@gmail.com> wrote:
Myself and many other developers have been bitten by the fact that maps are sorted if they have less than 33 elements. Not because we believed that we should rely on the sort ordering of a map, but because we *accidentally* wrote an implementation that did, and didn't test it with more than 32 elements. Then at some point later in actual use things get strange, and debugging the above scenario can be very difficult (but is of course obvious in retrospect). This could be opt-in or opt-out, all the same to me, although unless the performance impacts are huge I think that it would save new developers even more time than experienced developers and so should potentially be opt-out. After a while when you start to see things "showing up in weird orders" you have an intuition to go look for a map being enumerated, but that isn't something a beginner would likely think of. 

As far as I know this is an erlang thing, but I'm not too familiar with erlang and thought I'd float it by the elixir group first. I'm also not sure if its possible to change those constants based on Mix environments (or to change them at all), but I imagine that is where it will intersect with Elixir. 

--
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.

--
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.

--
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/l9s2xhyi.f95fde5a-5c38-40b7-ab2c-de3d3804b91f%40we.are.superhuman.com.

Zach Daniel

unread,
Oct 28, 2022, 2:08:42 AM10/28/22
to elixir-l...@googlegroups.com
Yeah, that makes sense. It would be worth thinking of other ways to avoid the issue of accidentally depending on a sorted map. Like since the implementation is opaque, perhaps it would be better if the keys were sorted in reverse by default? Probably something to talk to erlang people about.


On Fri, Oct 28, 2022 at 1:02 AM, José Valim <jose....@dashbit.co> wrote:
Oh, you didn’t say it was an env var either. :) I just assumed based on the casing.

In any case, that’s a C constant. It can only be changed while the VM is building.
On Fri, Oct 28, 2022 at 07:56 Zach Daniel <zachary.s.daniel@gmail.com> wrote:
Sorry, it isn't an environment variable as far as I can tell, its just a constant in `erl_map.c`. https://github.com/erlang/otp/blob/master/erts/emulator/beam/erl_map.c

In this case I was using string keys, but reducing the likelihood of this foot gun in any way is good :)


On Fri, Oct 28, 2022 at 12:34 AM, José Valim <jose.valim@dashbit.co> wrote:
Can you please provide the documentation for said environment variable from Erlang?

Also note that atom keys will likely no longer be sorted alphabetically in Erlang/OTP 26, which should help with said assumptions.
On Fri, Oct 28, 2022 at 06:20 Zach Daniel <zachary.s.daniel@gmail.com> wrote:
Myself and many other developers have been bitten by the fact that maps are sorted if they have less than 33 elements. Not because we believed that we should rely on the sort ordering of a map, but because we *accidentally* wrote an implementation that did, and didn't test it with more than 32 elements. Then at some point later in actual use things get strange, and debugging the above scenario can be very difficult (but is of course obvious in retrospect). This could be opt-in or opt-out, all the same to me, although unless the performance impacts are huge I think that it would save new developers even more time than experienced developers and so should potentially be opt-out. After a while when you start to see things "showing up in weird orders" you have an intuition to go look for a map being enumerated, but that isn't something a beginner would likely think of. 

As far as I know this is an erlang thing, but I'm not too familiar with erlang and thought I'd float it by the elixir group first. I'm also not sure if its possible to change those constants based on Mix environments (or to change them at all), but I imagine that is where it will intersect with Elixir. 

--
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+unsubscribe@googlegroups.com.

--
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+unsubscribe@googlegroups.com.

--
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+unsubscribe@googlegroups.com.

--
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+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4K9V95mQzqMuEUyintLqOzytwf%2BXS%3DujkGNpcu1kr0oXA%40mail.gmail.com.

Felipe Stival

unread,
Oct 28, 2022, 2:09:41 AM10/28/22
to elixir-l...@googlegroups.com
To change this value you'd need to recompile the VM, it is defined in a C macro and part of the ERTS.

On Fri, Oct 28, 2022, 05:20 Zach Daniel <zachary....@gmail.com> wrote:
Myself and many other developers have been bitten by the fact that maps are sorted if they have less than 33 elements. Not because we believed that we should rely on the sort ordering of a map, but because we *accidentally* wrote an implementation that did, and didn't test it with more than 32 elements. Then at some point later in actual use things get strange, and debugging the above scenario can be very difficult (but is of course obvious in retrospect). This could be opt-in or opt-out, all the same to me, although unless the performance impacts are huge I think that it would save new developers even more time than experienced developers and so should potentially be opt-out. After a while when you start to see things "showing up in weird orders" you have an intuition to go look for a map being enumerated, but that isn't something a beginner would likely think of. 

As far as I know this is an erlang thing, but I'm not too familiar with erlang and thought I'd float it by the elixir group first. I'm also not sure if its possible to change those constants based on Mix environments (or to change them at all), but I imagine that is where it will intersect with Elixir. 

--
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.

Boris Kuznetsov

unread,
Oct 29, 2022, 4:19:59 PM10/29/22
to elixir-l...@googlegroups.com
Could someone please share an example when it can lead to bugs in a system

To me maps are simple key/value data structure which gets accessed through direct work with a key or pattern matched against

On 28 Oct 2022, at 06:20, Zach Daniel <zachary....@gmail.com> wrote:

Myself and many other developers have been bitten by the fact that maps are sorted if they have less than 33 elements. Not because we believed that we should rely on the sort ordering of a map, but because we *accidentally* wrote an implementation that did, and didn't test it with more than 32 elements. Then at some point later in actual use things get strange, and debugging the above scenario can be very difficult (but is of course obvious in retrospect). This could be opt-in or opt-out, all the same to me, although unless the performance impacts are huge I think that it would save new developers even more time than experienced developers and so should potentially be opt-out. After a while when you start to see things "showing up in weird orders" you have an intuition to go look for a map being enumerated, but that isn't something a beginner would likely think of. 


As far as I know this is an erlang thing, but I'm not too familiar with erlang and thought I'd float it by the elixir group first. I'm also not sure if its possible to change those constants based on Mix environments (or to change them at all), but I imagine that is where it will intersect with Elixir. 

--

Zach Daniel

unread,
Oct 29, 2022, 6:27:51 PM10/29/22
to elixir-l...@googlegroups.com
The way that this can lead to bugs is when you dynamically build a map, and then later iterate over the keys and values in some way that depends on the order (which is the actual bug here) but you don't notice because the map has a stable sort. In this instance, we had code in AshPhoenix that was working with the params that come back from a Phoenix.HTML.FormData form, that looks like this:

%{"0" ⇒ …, "1" ⇒ …., "2" ⇒ ….}

And we then turn that into a structure like `[%{...}, %{...}, %{...}]` and we were not properly sorting. The test suite didn't ever use 10 or more elements, but when a user did, they saw their forms no longer coming back in the order they were in the HTML, but form 10 was after form 1, because the map was string key sorted. This is just one example, I've been bitten by this a few times. The actual problem is of course iterating over a map when the order matters, but the point is that by having a predictable, stable behavior below 32 elements, it increases the likelihood that a programmer wouldn't notice that they had done that.

With that said, based on the value being baked into the VM as a C constant, its definitely not worth the effort to find some way to alleviate this issue 😆


On Sat, Oct 29, 2022 at 4:19 PM, Boris Kuznetsov <m...@achempion.com> wrote:
Could someone please share an example when it can lead to bugs in a system

To me maps are simple key/value data structure which gets accessed through direct work with a key or pattern matched against

On 28 Oct 2022, at 06:20, Zach Daniel <zachary.s.daniel@gmail.com> wrote:

Myself and many other developers have been bitten by the fact that maps are sorted if they have less than 33 elements. Not because we believed that we should rely on the sort ordering of a map, but because we *accidentally* wrote an implementation that did, and didn't test it with more than 32 elements. Then at some point later in actual use things get strange, and debugging the above scenario can be very difficult (but is of course obvious in retrospect). This could be opt-in or opt-out, all the same to me, although unless the performance impacts are huge I think that it would save new developers even more time than experienced developers and so should potentially be opt-out. After a while when you start to see things "showing up in weird orders" you have an intuition to go look for a map being enumerated, but that isn't something a beginner would likely think of. 

As far as I know this is an erlang thing, but I'm not too familiar with erlang and thought I'd float it by the elixir group first. I'm also not sure if its possible to change those constants based on Mix environments (or to change them at all), but I imagine that is where it will intersect with Elixir. 

--
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+unsubscribe@googlegroups.com.

--
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+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/8C768E7E-61D7-4B69-956D-16567D2998DC%40achempion.com.

Boris Kuznetsov

unread,
Oct 30, 2022, 5:03:37 AM10/30/22
to 'Andrey Yugai' via elixir-lang-core
Interesting, I would never expect Map.to_list/1 like functions guarantee results in specific order especially if these maps are equal %{a: 1, b: 2}, %{b: 2, a: 1}.

In example you've given, we have numbers as string keys and the items order after conversion to a list you expect is unclear given that strings sorted differently than numbers ("9" > "100" => true).

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/l9uhk9qo.38af49dc-4df8-4c53-8ff7-493fad67302b%40we.are.superhuman.com.

Zach Daniel

unread,
Oct 30, 2022, 8:24:42 AM10/30/22
to elixir-l...@googlegroups.com
Yeah, basically if you use integers as keys, then you'd notice your bug at the 33rd key, whereas if they are strings as integers you'd notice it at the 10th key (or 11th if you started at 0).


On Sun, Oct 30, 2022 at 5:03 AM, Boris Kuznetsov <m...@achempion.com> wrote:
Interesting, I would never expect Map.to_list/1 like functions guarantee results in specific order especially if these maps are equal %{a: 1, b: 2}, %{b: 2, a: 1}.

In example you've given, we have numbers as string keys and the items order after conversion to a list you expect is unclear given that strings sorted differently than numbers ("9" > "100" => true).
On 30 Oct 2022, at 00:27, Zach Daniel <zachary.s.daniel@gmail.com> wrote:

The way that this can lead to bugs is when you dynamically build a map, and then later iterate over the keys and values in some way that depends on the order (which is the actual bug here) but you don't notice because the map has a stable sort. In this instance, we had code in AshPhoenix that was working with the params that come back from a Phoenix.HTML.FormData form, that looks like this:

%{"0" ⇒ …, "1" ⇒ …., "2" ⇒ ….}

And we then turn that into a structure like `[%{...}, %{...}, %{...}]` and we were not properly sorting. The test suite didn't ever use 10 or more elements, but when a user did, they saw their forms no longer coming back in the order they were in the HTML, but form 10 was after form 1, because the map was string key sorted. This is just one example, I've been bitten by this a few times. The actual problem is of course iterating over a map when the order matters, but the point is that by having a predictable, stable behavior below 32 elements, it increases the likelihood that a programmer wouldn't notice that they had done that.

With that said, based on the value being baked into the VM as a C constant, its definitely not worth the effort to find some way to alleviate this issue 😆


On Sat, Oct 29, 2022 at 4:19 PM, Boris Kuznetsov <me@achempion.com> wrote:
Could someone please share an example when it can lead to bugs in a system

To me maps are simple key/value data structure which gets accessed through direct work with a key or pattern matched against

On 28 Oct 2022, at 06:20, Zach Daniel <zachary.s.daniel@gmail.com> wrote:

Myself and many other developers have been bitten by the fact that maps are sorted if they have less than 33 elements. Not because we believed that we should rely on the sort ordering of a map, but because we *accidentally* wrote an implementation that did, and didn't test it with more than 32 elements. Then at some point later in actual use things get strange, and debugging the above scenario can be very difficult (but is of course obvious in retrospect). This could be opt-in or opt-out, all the same to me, although unless the performance impacts are huge I think that it would save new developers even more time than experienced developers and so should potentially be opt-out. After a while when you start to see things "showing up in weird orders" you have an intuition to go look for a map being enumerated, but that isn't something a beginner would likely think of. 

As far as I know this is an erlang thing, but I'm not too familiar with erlang and thought I'd float it by the elixir group first. I'm also not sure if its possible to change those constants based on Mix environments (or to change them at all), but I imagine that is where it will intersect with Elixir. 

--
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+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/a528c1bb-b8e1-429c-b1ff-a98db36ee2d6n%40googlegroups.com.

--
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+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/8C768E7E-61D7-4B69-956D-16567D2998DC%40achempion.com.


--
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+unsubscribe@googlegroups.com.

--
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+unsubscribe@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages