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

openSUSE Build Service is sponsored by