Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support to in place add/remove key/values of map in ets:select_replace with match spec #7309

Open
yushli opened this issue May 26, 2023 · 5 comments · May be fixed by #7326
Open

Add support to in place add/remove key/values of map in ets:select_replace with match spec #7309

yushli opened this issue May 26, 2023 · 5 comments · May be fixed by #7326
Assignees
Labels
enhancement team:VM Assigned to OTP team VM

Comments

@yushli
Copy link

yushli commented May 26, 2023

Is your feature request related to a problem? Please describe.

ets:select_replace/2 can use match spec to do in place replacement with List, which is efficient. But it doesn’t support updating map in place.

For example, the change to a list works:
ets:fun2ms(fun({K, L}) when is_list(L) → {K, [marker | L]} end).
Output:
[{{‘$1’,‘$2’},[{is_list,‘$2’}],[{{‘$1’,[marker|‘$2’]}}]}]

But for something similar with map:
ets:fun2ms(fun({K, Map}) when is_map(Map) → {K, Map#{marker => true}} end).
Output:
Error: the language element map (in body) cannot be translated into match_spec {error,transform_error}

Is Erlang/OTP team considering adding support to map as well?

Describe the solution you'd like

ets:select_replace/2 can use match spec to efficiently in place add/remove key/values from a map.

Describe alternatives you've considered

Right now in order to update a map, it needs to read from ets, make the changes, then copy the new map back to ets, which is very inefficient for bigger map. Since Erlang/OTP already support select by key with match spec, it would be consistent to support modification as well.

Additional context

@IngelaAndin IngelaAndin added the team:VM Assigned to OTP team VM label May 26, 2023
@sverker sverker linked a pull request May 30, 2023 that will close this issue
@sverker
Copy link
Contributor

sverker commented May 30, 2023

@yushli I did a working proposal in #7326. What do you think?

@yushli
Copy link
Author

yushli commented May 31, 2023

Looks like it is pretty good. Thanks for this quick working solution!
I just wonder if maps:merge can be added as well. It can be mimic by using multiple maps_put, but not as convenient as have a merge that can update multiple keys at once with simpler syntax.

@sverker
Copy link
Contributor

sverker commented May 31, 2023

The problem with BIFs like maps:merge is they can take arbitrary long time to finish if the maps are large enough. In order to not starve other Erlang processes from executing such BIFs might yield execution to be resumed at a later time. The match spec execution engine does not have support for yielding.

@yushli
Copy link
Author

yushli commented May 31, 2023

Got it. The solution is good enough for simple use cases. Look forward to seeing it merged into mainline.

@christhekeele
Copy link
Contributor

christhekeele commented Feb 12, 2024

Wanted to add more than a +1 for this feature, so added some thoughts here.

My use case is not with efficiency large maps, but with race conditions in a high-write-concurrency situation where multiple processes tend to want to update just specific values under different specific keys of a map. Being able to read and select_update overwrite just a single map key instead of the whole map would eliminate the major source of race conditions in what I'm working on.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement team:VM Assigned to OTP team VM
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants