Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:23
erlang
3251-Add-a-chapter-about-maps-to-the-Efficiency...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 3251-Add-a-chapter-about-maps-to-the-Efficiency-Guide.patch of Package erlang
From 8e6358e0f3bbf82384938197206100a4f071b8d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org> Date: Thu, 1 Jul 2021 07:25:27 +0200 Subject: [PATCH] Add a chapter about maps to the Efficiency Guide --- lib/stdlib/doc/src/maps.xml | 5 +- system/doc/efficiency_guide/maps.xml | 686 ++++++++++++++++++++++++ system/doc/efficiency_guide/part.xml | 1 + system/doc/efficiency_guide/xmlfiles.mk | 3 +- 4 files changed, 693 insertions(+), 2 deletions(-) create mode 100644 system/doc/efficiency_guide/maps.xml diff --git a/lib/stdlib/doc/src/maps.xml b/lib/stdlib/doc/src/maps.xml index 5df885fc96..fdca524153 100644 --- a/lib/stdlib/doc/src/maps.xml +++ b/lib/stdlib/doc/src/maps.xml @@ -30,7 +30,10 @@ <module since="OTP 17.0">maps</module> <modulesummary>Maps processing functions.</modulesummary> <description> - <p>This module contains functions for maps processing.</p> + <p>This module contains functions for maps processing. The + Efficiency Guide contains a chapter that describes <seeguide + marker="system/efficiency_guide:maps">how to use maps + efficiently</seeguide>.</p> </description> <datatypes> diff --git a/system/doc/efficiency_guide/maps.xml b/system/doc/efficiency_guide/maps.xml new file mode 100644 index 0000000000..140bdd549a --- /dev/null +++ b/system/doc/efficiency_guide/maps.xml @@ -0,0 +1,686 @@ +<?xml version="1.0" encoding="utf-8" ?> +<!DOCTYPE chapter SYSTEM "chapter.dtd"> + +<chapter> + <header> + <copyright> + <year>2021</year><year>2021</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + </legalnotice> + + <title>Maps</title> + <prepared>Bjorn Gustavsson</prepared> + <docno></docno> + <date>2021-07-01</date> + <rev></rev> + <file>maps.xml</file> + </header> + + <p>This guide to using maps efficiently starts with a brief section + on the choice between records or maps, followed by three sections + giving concrete (but brief) advice on using maps as an alternative to + records, as dictionaries, and as sets. The remaining sections dig + deeper, looking at how maps are implemented, the map syntax, and + finally the functions in the <seeerl + marker="stdlib:maps">maps</seeerl> module.</p> + + <p>Terminology used in this chapter:</p> + <list type="bulleted"> + <item>A map with at most 32 elements will informally be called a + <em>small map</em>.</item> + <item>A map with more than 32 elements will informally be called a + <em>large map</em>.</item> + </list> + + <section> + <title>Maps or Records?</title> + <p>If the advice in this chapter is followed, the performance of + records compared to using small maps instead of records is + expected to be similar. Therefore, the choice between records and + maps should be based on the desired properties of the data + structure and not performance.</p> + + <p>The advantages of records compared to maps are:</p> + + <list type="bulleted"> + <item>If the name of a record field is misspelled, there will be + a compilation error. If a map key is misspelled, the compiler + will give no warning and program will fail in some way when it + is run.</item> + + <item>Records will use slightly less memory than maps, and + performance is expected to be <em>slightly</em> better than maps + in most circumstances.</item> + </list> + + <p>The disadvantage of records compared to maps is that if a new + field is added to a record, all code that uses that record must be + recompiled. Because of that, it is recommended to only use records + within a unit of code that can easily be recompiled all at once, for + example within a single application or single module.</p> + </section> + + <section> + <title>Using Maps as an Alternative to Records</title> + + <list type="bulleted"> + <item><p>Use the map syntax instead of the functions in + the <seeerl marker="stdlib:maps">maps</seeerl> module.</p></item> + + <item><p>Avoid having more than 32 elements in the + map. As soon as there are more than 32 elements in the map, + it will require more memory and keys can no longer be shared + with other instances of the map.</p></item> + + <item><p>When creating a new map, always create it with all keys + that will ever be used. To maximize sharing of keys (thus + minimizing memory use), create a single function that constructs + the map using the map syntax and always use it.</p></item> + + <item><p>Always update the map using the + <c>:=</c> operator (that is, requiring that an element with + that key already exists). The <c>:=</c> operator is slightly + more efficient, and it helps catching mispellings of + keys.</p></item> + + <item><p>Whenever possible, match multiple map elements at + once.</p></item> + + <item><p>Whenever possible, update multiple map elements at + once.</p></item> + + <item><p>Avoid default values and the <seemfa + marker="stdlib:maps#get/3">maps:get/3</seemfa> function. If + there are default values, sharing of keys between different + instances of the map will be less effective, and it is not + possible to match multiple elements having default values in one + go. The <c>maps:get/3</c> function is <seeguide + marker="#maps_get_3">implemented in Erlang</seeguide>, making it + less efficient than <c>maps:get/2</c> or the map matching + syntax.</p></item> + + <item><p>To avoid having to deal with a map that may lack some keys, + <seemfa marker="stdlib:maps#merge/2">maps:merge/2</seemfa> + can efficiently add multiple default values. For example:</p> + <code type="erl"><![CDATA[ + DefaultMap = #{shoe_size => 42, editor => emacs}, + MapWithDefaultsApplied = maps:merge(DefaultMap, OtherMap)]]></code> + </item> + </list> + </section> + + <section> + <title>Using Maps as Dictionaries</title> + + <p>Using a map as a dictionary implies the following usage pattern:</p> + <list type="bulleted"> + <item><p>Keys are usually variables not known at compile-time.</p></item> + <item><p>There can be any number of elements in the map.</p></item> + <item><p>Usually, no more than one element is looked up or + updated at once.</p></item> + </list> + + <p>Given that usage pattern, the difference in performance between + using the map syntax and the maps module is usually + small. Therefore, which one to use is mostly a matter of + taste.</p> + + <p>Maps are usually the most efficient dictionary data structure, + with a few exceptions:</p> + + <list type="bulleted"> + <item><p>If it is necessary to frequently convert a + dictionary to a sorted list, or from a sorted list to a + dictionary, using <seeerl marker="stdlib:gb_trees">gb_trees</seeerl> + can be a better choice.</p></item> + + <item><p>If all keys are non-negative integers, the <seeerl + marker="stdlib:array">array</seeerl> module can be a better + choice.</p></item> + </list> + </section> + + <section> + <title>Using Maps as Sets</title> + + <p>Starting in OTP 24, the <seeerl marker="stdlib:sets">sets</seeerl> module + has an option to represent sets as maps. Examples:</p> + + <code type="erl"><![CDATA[ +1> sets:new([{version,2}]). +#{} +2> sets:from_list([x,y,z], [{version,2}]). +#{x => [],y => [],z => []}]]></code> + + <p><c>sets</c> backed by maps is generally the most efficient set + representation, with a few possible exceptions:</p> + + <list type="bulleted"> + <item><p><seemfa + marker="stdlib:ordsets#intersection/2">ordsets:intersection/2</seemfa> + can be more efficient than <seemfa + marker="stdlib:sets#intersection/2">sets:intersection/2</seemfa>. + If the intersection operation is frequently used and operations + that operate on a single element in a set (such as + <c>is_element/2</c>) are avoided, <seeerl + marker="stdlib:ordsets">ordsets</seeerl> can be a better + choice than <seeerl marker="stdlib:sets">sets</seeerl>.</p></item> + + <item><p>If the intersection operation is frequently used and operations + that operate on a single element in a set (such as + <c>is_element/2</c>) must also be efficient, <seeerl + marker="stdlib:gb_sets">gb_sets</seeerl> can potentially be a + better choice than <seeerl marker="stdlib:sets">sets</seeerl>.</p></item> + + <item><p>If the elements of the set are integers in a fairly + compact range, the set can be represented as an integer where + each bit represents an element in the set. The union operation + is performed by <c>bor</c> and the intersection operation by + <c>band</c>.</p></item> + </list> + </section> + + <section> + <title>How Maps are Implemented</title> + <p>Internally, maps have two distinct representations depending on + the number of elements in the map. The representation changes + when a map grows beyond 32 elements, or when it shrinks to 32 + elements or less.</p> + + <list type="bulleted"> + <item>A map with at most 32 elements has a compact + representation, making it suitable as an alternative to + records.</item> + <item>A map with more than 32 elements is represented as a tree + that can be efficiently searched and updated regardless of how + many elements there are.</item> + </list> + + <section> + <title>How Small Maps are Implemented</title> + <p>A small map looks like this inside the runtime system:</p> + <table align="left"> + <row> + <cell align="center"><c>FLATMAP</c></cell> + <cell align="center"><em>N</em></cell> + <cell align="center"><em>Keys</em></cell> + <cell align="center"><em>Value1</em></cell> + <cell align="center"><em>. . .</em></cell> + <cell align="center"><em>ValueN</em></cell> + </row> + <tcaption>The representation of a small map</tcaption> + </table> + + <taglist> + <tag><c>FLATMAP</c></tag> + <item>The tag for a small map (called <em>flat map</em> in + the source code for the runtime system).</item> + + <tag>N</tag> + <item>The number of elements in the map.</item> + + <tag>Keys</tag> + <item>A tuple with keys of the map: <c>{Key1,...,KeyN}</c>. The + keys are sorted.</item> + + <tag>Value1</tag> + <item>The value corresponding to the first key in the key tuple.</item> + + <tag>ValueN</tag> + <item>The value corresponding to the last key in the key tuple.</item> + </taglist> + + <p>As an example, let us look at how the map <c>#{a => foo, z => bar}</c> + is represented:</p> + + <table align="left"> + <row> + <cell align="center"><c>FLATMAP</c></cell> + <cell align="center"><em>2</em></cell> + <cell align="center"><em>{a,z}</em></cell> + <cell align="center"><em>foo</em></cell> + <cell align="center"><em>bar</em></cell> + </row> + <tcaption>#{a => foo, z => bar}</tcaption> + </table> + + <p>Let us update the map: <c>M#{q => baz}</c>. The map now looks + like this:</p> + + <table align="left"> + <row> + <cell align="center"><c>FLATMAP</c></cell> + <cell align="center"><em>3</em></cell> + <cell align="center"><em>{a,q,z}</em></cell> + <cell align="center"><em>foo</em></cell> + <cell align="center"><em>baz</em></cell> + <cell align="center"><em>bar</em></cell> + </row> + <tcaption>#{a => foo, q => baz, z => bar}</tcaption> + </table> + + <p>Finally, change the value of one element: <c>M#{z := + bird}</c>. The map now looks like this:</p> + + <table align="left"> + <row> + <cell align="center"><c>FLATMAP</c></cell> + <cell align="center"><em>3</em></cell> + <cell align="center"><em>{a,q,z}</em></cell> + <cell align="center"><em>foo</em></cell> + <cell align="center"><em>baz</em></cell> + <cell align="center"><em>bird</em></cell> + </row> + <tcaption>#{a => foo, q => baz, z => bird}</tcaption> + </table> + + <p>When the value for an existing key is updated, the key tuple is not + updated, allowing the key tuple to be shared with other instances of the + map that have the same keys. In fact, the key tuple can be shared between all + maps with the same keys with some care. To arrange that, define a function that + returns a map. For example:</p> + + <code type="erl"><![CDATA[ +new() -> + #{a => default, b => default, c => default}.]]></code> + + <p>Defined like this, the key tuple <c>{a,b,c}</c> will be a + global literal. To ensure that the key tuple is shared + when creating an instance of the map, always call + <c>new()</c> and modify the returned map:</p> + + <code type="erl"><![CDATA[ + (SOME_MODULE:new())#{a := 42}.]]></code> + + <p>Using the map syntax with small maps is particularly + efficient. As long as the keys are known at compile-time, the + map is updated in one go, making the time to update a map + essentially constant regardless of the number of keys + updated. The same goes for matching. (When the keys are + variables, one or more of the keys could be identical, so the + operations need to be performed sequentially from left to + right.)</p> + + <p>The memory size for a small map is the size of all keys and values + plus 5 words. See <seeguide marker="advanced#memory">Advanced</seeguide> + for more information about memory sizes.</p> + </section> + + <section> + <title>How Large Maps are Implemented</title> + + <p>A map with more than 32 elements is implemented as a <url + href="https://en.wikipedia.org/wiki/Hash_array_mapped_trie">Hash + array mapped trie (HAMT)</url>. A large map can be efficiently + searched and updated regardless of the number of elements in the + map.</p> + + <p>There is less performance to be gained by matching or + updating multiple elements using the map syntax on a large map + compared to a small map. The execution time is roughly proportional + to the number of elements matched or updated.</p> + + <p>The storage overhead for a large map is higher than for a + small map. For a large map, the extra number of words besides + the keys and values is roughly proportional to the number of + elements. For a map with 33 elements the overhead is at + least 53 heap words according to the formula in <seeguide + marker="advanced#memory">Advanced</seeguide> (compared to 5 + extra words for a small map regardless of the number of + elements).</p> + + <p>When a large map is updated, the updated map and the original + map will share common parts of the HAMT, but sharing will never + be as effective as the best possible sharing of the key tuple + for small maps.</p> + + <p>Therefore, if maps are used instead of records and it is + expected that many instances of the map will be created, it is + more efficient from a memory standpoint to avoid using large + maps (for example, by grouping related map elements into sub + maps to reduce the number of elements).</p> + </section> + </section> + + <section> + <title>Using the Map Syntax</title> + + <p>Using the map syntax is usually slightly more efficient than + using the corresponding function in the <seeerl + marker="stdlib:maps">maps</seeerl> module.</p> + + <p>The gain in efficiency for the map syntax is more noticeable + for the following operations that can only be achieved using the + map syntax:</p> + + <list type="bulleted"> + <item><p>Matching multiple literal keys</p></item> + <item><p>Updating multiple literal keys</p></item> + <item><p>Adding multiple literal keys to a map</p></item> + </list> + + <p>For example:</p> + + <p><em>DO</em></p> + <code type="erl"><![CDATA[ + Map = Map1#{x := X, y := Y, z := Z}]]></code> + + <p><em>DO NOT</em></p> + <code type="erl"><![CDATA[ + Map2 = maps:update(x, X, Map1), + Map3 = maps:update(y, Y, Map2), + Map = maps:update(z, Z, Map3)]]></code> + + <p>If the map is a small map, the first example runs roughly + three times as fast.</p> + + <p>Note that for variable keys, the elements are updated + sequentially from left to right. For example, given the following + update with variable keys:</p> + + <code type="erl"><![CDATA[ + Map = Map1#{Key1 := X, Key2 := Y, Key3 := Z}]]></code> + + <p>the compiler rewrites it like this to ensure that the updates + are applied from left to right:</p> + + <code type="erl"><![CDATA[ + Map2 = Map1#{Key1 := X}, + Map3 = Map2#{Key2 := Y}, + Map = Map3#{Key3 := Z}]]></code> + + <p>If a key is known to exist in a map, using the <c>:=</c> + operator is slightly more efficient than using the <c>=></c> + operator for a small map.</p> + </section> + + <section> + <title>Using the Functions in the maps Module</title> + + <p>Here follows some notes about most of the functions in the + <c>maps</c> module. For each function, the implementation language + (C or Erlang) is stated. The reason we mention the language is + that it gives an hint about how efficient the function is:</p> + + <list type="bulleted"> + <item><p>If a function is implemented in C, it is pretty much + impossible to implement the same functionality more efficiently + in Erlang.</p></item> + + <item><p>However, it might be possible to beat the <c>maps</c> + modules functions implemented in Erlang, because they are + generally implemented in a way that attempts to make the performance + reasonable for all possible inputs.</p> + + <p>For example, <seemfa + marker="stdlib:maps#map/2">maps:map/2</seemfa> iterates over + all elements of the map, calling the mapping fun, collects the + updated map elements in a list, and finally converts the list + back to a map using <seemfa + marker="stdlib:maps#from_list/1">maps:from_list/1</seemfa>. If + it is known that at most one percent of the values in the map + will change, it can be more efficient to update only the + changed values.</p></item> + </list> + + <note><p>The implementation details given in this section can + change in the future.</p></note> + + <section> + <title>maps:filter/2</title> + <p><seemfa marker="stdlib:maps#filter/2">maps:filter/2</seemfa> + is implemented in Erlang. It creates a new map using <seemfa + marker="stdlib:maps#from_list/1">maps:from_list/1</seemfa>. If + it is known that only a minority of the values will be removed, + it can be more efficient to avoid <c>maps:filter/2</c> and write + a function that will use <seemfa + marker="stdlib:maps#remove/2">maps:remove/3</seemfa> to remove + the unwanted values.</p> + </section> + + <section> + <title>maps:filtermap/2</title> + <p><seemfa + marker="stdlib:maps#filtermap/2">maps:filtermap/2</seemfa> is + implemented in Erlang. It creates a new map using <seemfa + marker="stdlib:maps#from_list/1">maps:from_list/1</seemfa>. See + the notes for <c>maps:map/2</c> and <c>maps:filter/2</c> for + hints on how to implement a more efficient version.</p> + </section> + + <section> + <title>maps:find/2</title> + <p><seemfa marker="stdlib:maps#find/2">maps:find/2</seemfa> is + implemented in C.</p> + <p>Using the map matching syntax instead of <c>maps:find/2</c> + will be slightly more efficient since building an + <c>{ok,Value}</c> tuple will be avoided.</p> + </section> + + <section> + <title>maps:get/2</title> + <p>As an optimization, the compiler will rewrite a call to <seemfa + marker="stdlib:maps#get/2">maps:get/2</seemfa> to a call to the + guard BIF <seemfa + marker="erts:erlang#map_get/2">map_get/2</seemfa>. A call to a + guard BIF is more efficient than calls to other BIFs, making the + performance similar to using the map matching syntax.</p> + + <p>If the map is small and the keys are constants known at + compile-time, using the map matching syntax will be more + efficient than multiple calls to <c>maps:get/2</c>.</p> + </section> + + <section> + <marker id="maps_get_3"/> + <title>maps:get/3</title> + <p><seemfa marker="stdlib:maps#get/3">maps:get/3</seemfa> + is implemented in Erlang essentially like this:</p> + + <code type="erl"><![CDATA[ +get(Key, Map, Default) -> + case Map of + #{Key := Value} -> Value; + #{} -> Default + end.]]></code> + + <p>Therefore, a call <c>maps:get/3</c> is more expensive than a + call to <c>maps:get/2</c>.</p> + + <p>If a small map is used as alternative to using a record, + instead of calling <c>maps:get/3</c> multiple times to handle + default values, consider putting the default values in a map and + merging that map with the other map:</p> + + <code type="erl"><![CDATA[ + DefaultMap = #{Key1 => Value2, Key2 => Value2, ..., KeyN => ValueN}, + MapWithDefaultsApplied = maps:merge(DefaultMap, OtherMap)]]></code> + + <p>Whether that is faster than calling <c>maps:get/3</c> + multiple times depends on the size of the map and the number of + default values.</p> + </section> + + <section> + <title>maps:intersect/2, maps:intersect_with/3</title> + <p><seemfa marker="stdlib:maps#intersect/2">maps:intersect/2</seemfa> and + <seemfa marker="stdlib:maps#intersect_with/3">maps:intersect_with/3</seemfa> + are implemented in Erlang. They both create new maps using <seemfa + marker="stdlib:maps#from_list/1">maps:from_list/1</seemfa>.</p> + + <note><p>A map is usually the most efficient way to implement a + set, but an exception is the intersection operation, where + <seemfa + marker="stdlib:ordsets#intersection/2">ordsets:intersection/2</seemfa> + used on <seeerl marker="stdlib:ordsets">ordsets</seeerl> can be more + efficient than <c>maps:intersect/2</c> on sets implemented as maps.</p></note> + </section> + + <section> + <title>maps:from_list/1</title> + <p><seemfa marker="stdlib:maps#from_list/1">maps:from_list/1</seemfa> is + implemented in C.</p> + </section> + + <section> + <title>maps:from_keys/2</title> + <p><seemfa marker="stdlib:maps#from_keys/2">maps:from_keys/2</seemfa> is + implemented in C.</p> + </section> + + <section> + <title>maps:is_key/2</title> + <p>As an optimization, the compiler rewrites calls to <seemfa + marker="stdlib:maps#is_key/2">maps:is_key/2</seemfa> to calls + to the guard BIF <seemfa + marker="erts:erlang#is_map_key/2">is_map_key/2</seemfa>. A call + to a guard BIF is more efficient than calls to other BIFs, + making the performance similar to using the map matching syntax.</p> + </section> + + <section> + <title>maps:iterator/1</title> + <p><seemfa marker="stdlib:maps#iterator/1">maps:iterator/1</seemfa> + is efficiently implemented in C and Erlang.</p> + </section> + + <section> + <title>maps:keys/1</title> + <p><seemfa marker="stdlib:maps#keys/1">maps:keys/1</seemfa> is + implemented in C. If the resulting list needs to be ordered, use + <seemfa marker="stdlib:lists#sort/1">lists:sort/1</seemfa> to + sort the result.</p> + </section> + + <section> + <title>maps:map/2</title> + <p><seemfa marker="stdlib:maps#map/2">maps:map/2</seemfa> is + implemented in Erlang. It creates a new map using <seemfa + marker="stdlib:maps#from_list/1">maps:from_list/1</seemfa>. If + it is known that only a minority of the values will be updated, + it can be more efficient to avoid <c>maps:map/2</c> and write a + function that will call <seemfa + marker="stdlib:maps#update/3">maps:update/3</seemfa> to update + only the values that have changed.</p> + </section> + + <section> + <title>maps:merge/2</title> + <p><seemfa marker="stdlib:maps#merge/2">maps:merge/2</seemfa> + is implemented in C.</p> + </section> + + <section> + <title>maps:merge_with/3</title> + <p><seemfa marker="stdlib:maps#merge_with/3">maps:merge_with/3</seemfa> + is implemented in Erlang. It updates and returns the larger of the + two maps.</p> + </section> + + <section> + <title>maps:new/0</title> + <p>The compiler rewrites a call to <seemfa + marker="stdlib:maps#new/0">maps:new/0</seemfa> to using the + syntax <c>#{}</c> for constructing an empty map.</p> + </section> + + <section> + <title>maps:next/1</title> + <p><seemfa marker="stdlib:maps#next/1">maps:next/1</seemfa> + is efficiently implemented in C and Erlang.</p> + </section> + + <section> + <title>maps:put/3</title> + <p><seemfa marker="stdlib:maps#put/3">maps:put/3</seemfa> is + implemented in C.</p> + <p>If the key is known to already exist in the map, <seemfa + marker="stdlib:maps#update/3">maps:update/3</seemfa> is + slightly more efficient than <c>maps:put/3</c>.</p> + <p>If the keys are constants known at compile-time, using the + map update syntax with the <c>=></c> operator is more + efficient than multiple calls to <c>maps:put/3</c>, + especially for small maps.</p> + </section> + + <section> + <title>maps:remove/2</title> + <p><seemfa marker="stdlib:maps#remove/2">maps:remove/2</seemfa> + is implemented in C.</p> + </section> + + <section> + <title>maps:size/1</title> + <p>As an optimization, the compiler rewrites calls to + <seemfa marker="stdlib:maps#size/1">maps:size/1</seemfa> + to calls to the guard BIF <seemfa + marker="erts:erlang#map_size/1">map_size/1</seemfa>. + Calls to guard BIFs are more efficient than calls to other BIFs.</p> + </section> + + <section> + <title>maps:take/2</title> + <p><seemfa marker="stdlib:maps#take/2">maps:take/2</seemfa> + is implemented in C.</p> + </section> + + <section> + <title>maps:to_list/1</title> + <p><seemfa + marker="stdlib:maps#to_list/1">maps:to_list/1</seemfa> is + efficiently implemented in C and Erlang. If the resulting list + needs to be ordered, use <seemfa + marker="stdlib:lists#sort/1">lists:sort/1</seemfa> to sort + the result.</p> + + <note><p>Maps are usually more performant than <seeerl + marker="stdlib:gb_trees">gb_trees</seeerl>, but if it is + necessary to frequently convert to and from sorted lists, + <c>gb_trees</c> can be a better choice.</p></note> + </section> + + <section> + <title>maps:update/3</title> + <p><seemfa marker="stdlib:maps#update/3">maps:update/3</seemfa> + is implemented in C.</p> + + <p>If the keys are constants known at compile-time, using the + map update syntax with the <c>:=</c> operator is more + efficient than multiple calls to <c>maps:update/3</c>, + especially for small maps.</p> + </section> + + <section> + <title>maps:values/1</title> + <p><seemfa marker="stdlib:maps#values/1">maps:values/1</seemfa> + is implemented in C.</p> + </section> + + <section> + <title>maps:with/2</title> + <p><seemfa marker="stdlib:maps#with/2">maps:with/2</seemfa> + is implemented in Erlang. It creates a new map using <seemfa + marker="stdlib:maps#from_list/1">maps:from_list/1</seemfa>.</p> + </section> + + <section> + <title>maps:without/2</title> + <p><seemfa marker="stdlib:maps#without/2">maps:without/2</seemfa> + is implemented in Erlang. It returns a modified copy of the + input map.</p> + </section> + </section> +</chapter> diff --git a/system/doc/efficiency_guide/part.xml b/system/doc/efficiency_guide/part.xml index 5673ddd320..1d65b3104a 100644 --- a/system/doc/efficiency_guide/part.xml +++ b/system/doc/efficiency_guide/part.xml @@ -32,6 +32,7 @@ <xi:include href="myths.xml"/> <xi:include href="commoncaveats.xml"/> <xi:include href="binaryhandling.xml"/> + <xi:include href="maps.xml"/> <xi:include href="listhandling.xml"/> <xi:include href="functions.xml"/> <xi:include href="tablesDatabases.xml"/> diff --git a/system/doc/efficiency_guide/xmlfiles.mk b/system/doc/efficiency_guide/xmlfiles.mk index e275823dd1..3df2e8bd21 100644 --- a/system/doc/efficiency_guide/xmlfiles.mk +++ b/system/doc/efficiency_guide/xmlfiles.mk @@ -24,7 +24,8 @@ EFF_GUIDE_CHAPTER_FILES = \ functions.xml \ introduction.xml \ listhandling.xml \ - myths.xml \ + maps.xml \ + myths.xml \ part.xml \ processes.xml \ profiling.xml \ -- 2.31.1
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor