aboutsummaryrefslogtreecommitdiffstats
path: root/system
diff options
context:
space:
mode:
authorSverker Eriksson <[email protected]>2017-02-03 17:01:52 +0100
committerSverker Eriksson <[email protected]>2017-02-03 17:01:52 +0100
commit69b928b12d9206d00879c08e46143f599f9dc34e (patch)
treefde8905a6ca71c797725a33895321c67e81c3645 /system
parent4b97d656a9e1774fd4ff984014f085ad661a4fdb (diff)
parent1923315e618bea9fb23fc3237541f95a0accc266 (diff)
downloadotp-69b928b12d9206d00879c08e46143f599f9dc34e.tar.gz
otp-69b928b12d9206d00879c08e46143f599f9dc34e.tar.bz2
otp-69b928b12d9206d00879c08e46143f599f9dc34e.zip
Merge branch 'master' into sverker/enif_select
Diffstat (limited to 'system')
-rw-r--r--system/doc/efficiency_guide/advanced.xml12
-rw-r--r--system/doc/efficiency_guide/binaryhandling.xml81
-rw-r--r--system/doc/efficiency_guide/commoncaveats.xml8
-rw-r--r--system/doc/efficiency_guide/functions.xml11
-rw-r--r--system/doc/efficiency_guide/introduction.xml8
-rw-r--r--system/doc/efficiency_guide/listhandling.xml16
-rw-r--r--system/doc/efficiency_guide/myths.xml108
-rw-r--r--system/doc/efficiency_guide/part.xml1
-rw-r--r--system/doc/efficiency_guide/processes.xml10
-rw-r--r--system/doc/efficiency_guide/retired_myths.xml63
-rw-r--r--system/doc/reference_manual/character_set.xml6
-rw-r--r--system/doc/reference_manual/code_loading.xml2
-rw-r--r--system/doc/reference_manual/data_types.xml5
-rw-r--r--system/doc/reference_manual/errors.xml8
-rw-r--r--system/doc/reference_manual/expressions.xml10
-rw-r--r--system/doc/reference_manual/introduction.xml4
-rw-r--r--system/doc/reference_manual/macros.xml3
-rw-r--r--system/doc/reference_manual/records.xml6
-rw-r--r--system/doc/reference_manual/typespec.xml89
-rw-r--r--system/doc/tutorial/c_port.xmlsrc2
-rw-r--r--system/doc/tutorial/c_portdriver.xmlsrc4
21 files changed, 226 insertions, 231 deletions
diff --git a/system/doc/efficiency_guide/advanced.xml b/system/doc/efficiency_guide/advanced.xml
index eee2648f34..e1760d0ded 100644
--- a/system/doc/efficiency_guide/advanced.xml
+++ b/system/doc/efficiency_guide/advanced.xml
@@ -87,15 +87,15 @@
</row>
<row>
<cell>Small Map</cell>
- <cell>4 words + 2 words per entry (key and value) + the size of each key and value pair.</cell>
+ <cell>5 words + the size of all keys and values.</cell>
</row>
<row>
- <cell>Large Map</cell>
+ <cell>Large Map (> 32 keys)</cell>
<cell>
- At least, 2 words + 2 x <c>N</c> words + 2 x log16(<c>N</c>) words +
- the size of each key and value pair, where <c>N</c> is the number of pairs in the Map.
- A large Map is represented as a tree internally where each node in the tree is a
- "sparse tuple" of arity 16.
+ <c>N</c> x <c>F</c> words + the size of all keys and values.<br></br>
+ <c>N</c> is the number of keys in the Map.<br></br>
+ <c>F</c> is a sparsity factor that can vary between 1.6 and 1.8
+ due to the probabilistic nature of the internal HAMT data structure.
</cell>
</row>
<row>
diff --git a/system/doc/efficiency_guide/binaryhandling.xml b/system/doc/efficiency_guide/binaryhandling.xml
index 0295d18644..91fd9a7cd9 100644
--- a/system/doc/efficiency_guide/binaryhandling.xml
+++ b/system/doc/efficiency_guide/binaryhandling.xml
@@ -32,12 +32,9 @@
<file>binaryhandling.xml</file>
</header>
- <p>In R12B, the most natural way to construct and match binaries is
- significantly faster than in earlier releases.</p>
+ <p>Binaries can be efficiently built in the following way:</p>
- <p>To construct a binary, you can simply write as follows:</p>
-
- <p><em>DO</em> (in R12B) / <em>REALLY DO NOT</em> (in earlier releases)</p>
+ <p><em>DO</em></p>
<code type="erl"><![CDATA[
my_list_to_binary(List) ->
my_list_to_binary(List, <<>>).
@@ -47,21 +44,13 @@ my_list_to_binary([H|T], Acc) ->
my_list_to_binary([], Acc) ->
Acc.]]></code>
- <p>In releases before R12B, <c>Acc</c> is copied in every iteration.
- In R12B, <c>Acc</c> is copied only in the first iteration and extra
- space is allocated at the end of the copied binary. In the next iteration,
- <c>H</c> is written into the extra space. When the extra space runs out,
- the binary is reallocated with more extra space. The extra space allocated
- (or reallocated) is twice the size of the
- existing binary data, or 256, whichever is larger.</p>
-
- <p>The most natural way to match binaries is now the fastest:</p>
+ <p>Binaries can be efficiently matched like this:</p>
- <p><em>DO</em> (in R12B)</p>
+ <p><em>DO</em></p>
<code type="erl"><![CDATA[
my_binary_to_list(<<H,T/binary>>) ->
[H|my_binary_to_list(T)];
-my_binary_to_list(<<>>) -> [].]]></code>
+my_binary_to_list(<<>>) -> [].]]></code>
<section>
<title>How Binaries are Implemented</title>
@@ -138,10 +127,7 @@ my_binary_to_list(<<>>) -> [].]]></code>
pointer to the binary data. For each field that is matched out of
a binary, the position in the match context is incremented.</p>
- <p>In R11B, a match context was only used during a binary matching
- operation.</p>
-
- <p>In R12B, the compiler tries to avoid generating code that
+ <p>The compiler tries to avoid generating code that
creates a sub binary, only to shortly afterwards create a new match
context and discard the sub binary. Instead of creating a sub binary,
the match context is kept.</p>
@@ -155,7 +141,7 @@ my_binary_to_list(<<>>) -> [].]]></code>
<section>
<title>Constructing Binaries</title>
- <p>In R12B, appending to a binary or bitstring
+ <p>Appending to a binary or bitstring
is specially optimized by the <em>runtime system</em>:</p>
<code type="erl"><![CDATA[
@@ -292,7 +278,7 @@ Bin = <<Bin1,...>> %% Bin1 will be COPIED
<p>Let us revisit the example in the beginning of the previous section:</p>
- <p><em>DO</em> (in R12B)</p>
+ <p><em>DO</em></p>
<code type="erl"><![CDATA[
my_binary_to_list(<<H,T/binary>>) ->
[H|my_binary_to_list(T)];
@@ -304,15 +290,14 @@ my_binary_to_list(<<>>) -> [].]]></code>
byte of the binary. 1 byte is matched out and the match context
is updated to point to the second byte in the binary.</p>
- <p>In R11B, at this point a
- <seealso marker="#sub_binary">sub binary</seealso>
- would be created. In R12B,
- the compiler sees that there is no point in creating a sub binary,
- because there will soon be a call to a function (in this case,
+ <p>At this point it would make sense to create a
+ <seealso marker="#sub_binary">sub binary</seealso>,
+ but in this particular example the compiler sees that
+ there will soon be a call to a function (in this case,
to <c>my_binary_to_list/1</c> itself) that immediately will
create a new match context and discard the sub binary.</p>
- <p>Therefore, in R12B, <c>my_binary_to_list/1</c> calls itself
+ <p>Therefore <c>my_binary_to_list/1</c> calls itself
with the match context instead of with a sub binary. The instruction
that initializes the matching operation basically does nothing
when it sees that it was passed a match context instead of a binary.</p>
@@ -321,34 +306,10 @@ my_binary_to_list(<<>>) -> [].]]></code>
the match context will simply be discarded (removed in the next
garbage collection, as there is no longer any reference to it).</p>
- <p>To summarize, <c>my_binary_to_list/1</c> in R12B only needs to create
- <em>one</em> match context and no sub binaries. In R11B, if the binary
- contains <em>N</em> bytes, <em>N+1</em> match contexts and <em>N</em>
- sub binaries are created.</p>
-
- <p>In R11B, the fastest way to match binaries is as follows:</p>
+ <p>To summarize, <c>my_binary_to_list/1</c> only needs to create
+ <em>one</em> match context and no sub binaries.</p>
- <p><em>DO NOT</em> (in R12B)</p>
- <code type="erl"><![CDATA[
-my_complicated_binary_to_list(Bin) ->
- my_complicated_binary_to_list(Bin, 0).
-
-my_complicated_binary_to_list(Bin, Skip) ->
- case Bin of
- <<_:Skip/binary,Byte,_/binary>> ->
- [Byte|my_complicated_binary_to_list(Bin, Skip+1)];
- <<_:Skip/binary>> ->
- []
- end.]]></code>
-
- <p>This function cleverly avoids building sub binaries, but it cannot
- avoid building a match context in each recursion step.
- Therefore, in both R11B and R12B,
- <c>my_complicated_binary_to_list/1</c> builds <em>N+1</em> match
- contexts. (In a future Erlang/OTP release, the compiler might be able
- to generate code that reuses the match context.)</p>
-
- <p>Returning to <c>my_binary_to_list/1</c>, notice that the match context
+ <p>Notice that the match context in <c>my_binary_to_list/1</c>
was discarded when the entire binary had been traversed. What happens if
the iteration stops before it has reached the end of the binary? Will
the optimization still work?</p>
@@ -544,5 +505,15 @@ count3(<<>>, Count) -> Count.]]></code>
not matched out.</p>
</section>
</section>
+
+ <section>
+ <title>Historical Note</title>
+
+ <p>Binary handling was significantly improved in R12B. Because
+ code that was efficient in R11B might not be efficient in R12B,
+ and vice versa, earlier revisions of this Efficiency Guide contained
+ some information about binary handling in R11B.</p>
+ </section>
+
</chapter>
diff --git a/system/doc/efficiency_guide/commoncaveats.xml b/system/doc/efficiency_guide/commoncaveats.xml
index ecfeff0349..94b1c0b222 100644
--- a/system/doc/efficiency_guide/commoncaveats.xml
+++ b/system/doc/efficiency_guide/commoncaveats.xml
@@ -148,10 +148,10 @@ multiple_setelement(T0) ->
<p><c>size/1</c> returns the size for both tuples and binaries.</p>
- <p>Using the new BIFs <c>tuple_size/1</c> and <c>byte_size/1</c>, introduced
- in R12B, gives the compiler and the runtime system more opportunities for
- optimization. Another advantage is that the new BIFs can help Dialyzer to
- find more bugs in your program.</p>
+ <p>Using the BIFs <c>tuple_size/1</c> and <c>byte_size/1</c>
+ gives the compiler and the runtime system more opportunities for
+ optimization. Another advantage is that the BIFs give Dialyzer more
+ type information.</p>
</section>
<section>
diff --git a/system/doc/efficiency_guide/functions.xml b/system/doc/efficiency_guide/functions.xml
index 4a8248e65c..1d0f1f68b7 100644
--- a/system/doc/efficiency_guide/functions.xml
+++ b/system/doc/efficiency_guide/functions.xml
@@ -65,7 +65,7 @@ atom_map1(six) -> 6.</code>
thus, quite efficient even if there are many values) to select which
one of the first three clauses to execute (if any).</item>
- <item>>If none of the first three clauses match, the fourth clause
+ <item>If none of the first three clauses match, the fourth clause
match as a variable always matches.</item>
<item>If the guard test <c>is_integer(Int)</c> succeeds, the fourth
@@ -183,15 +183,6 @@ explicit_map_pairs(Map, Xs0, Ys0) ->
A fun contains an (indirect) pointer to the function that implements
the fun.</p>
- <warning><p><em>Tuples are not fun(s)</em>.
- A "tuple fun", <c>{Module,Function}</c>, is not a fun.
- The cost for calling a "tuple fun" is similar to that
- of <c>apply/3</c> or worse.
- Using "tuple funs" is <em>strongly discouraged</em>,
- as they might not be supported in a future Erlang/OTP release,
- and because there exists a superior alternative from R10B,
- namely the <c>fun Module:Function/Arity</c> syntax.</p></warning>
-
<p><c>apply/3</c> must look up the code for the function to execute
in a hash table. It is therefore always slower than a
direct call or a fun call.</p>
diff --git a/system/doc/efficiency_guide/introduction.xml b/system/doc/efficiency_guide/introduction.xml
index ca4a41c798..b650008ae8 100644
--- a/system/doc/efficiency_guide/introduction.xml
+++ b/system/doc/efficiency_guide/introduction.xml
@@ -46,14 +46,6 @@
to find out where the performance bottlenecks are and optimize only the
bottlenecks. Let other code stay as clean as possible.</p>
- <p>Fortunately, compiler and runtime optimizations introduced in
- Erlang/OTP R12B makes it easier to write code that is both clean and
- efficient. For example, the ugly workarounds needed in R11B and earlier
- releases to get the most speed out of binary pattern matching are
- no longer necessary. In fact, the ugly code is slower
- than the clean code (because the clean code has become faster, not
- because the uglier code has become slower).</p>
-
<p>This Efficiency Guide cannot really teach you how to write efficient
code. It can give you a few pointers about what to avoid and what to use,
and some understanding of how certain language features are implemented.
diff --git a/system/doc/efficiency_guide/listhandling.xml b/system/doc/efficiency_guide/listhandling.xml
index 2ebc877820..ec258d7c2a 100644
--- a/system/doc/efficiency_guide/listhandling.xml
+++ b/system/doc/efficiency_guide/listhandling.xml
@@ -90,7 +90,7 @@ tail_recursive_fib(N, Current, Next, Fibs) ->
<p>Lists comprehensions still have a reputation for being slow.
They used to be implemented using funs, which used to be slow.</p>
- <p>In recent Erlang/OTP releases (including R12B), a list comprehension:</p>
+ <p>A list comprehension:</p>
<code type="erl"><![CDATA[
[Expr(E) || E <- List]]]></code>
@@ -102,7 +102,7 @@ tail_recursive_fib(N, Current, Next, Fibs) ->
[Expr(E)|'lc^0'(Tail, Expr)];
'lc^0'([], _Expr) -> [].</code>
- <p>In R12B, if the result of the list comprehension will <em>obviously</em>
+ <p>If the result of the list comprehension will <em>obviously</em>
not be used, a list will not be constructed. For example, in this code:</p>
<code type="erl"><![CDATA[
@@ -131,6 +131,14 @@ some_function(...),
'lc^0'(Tail, Expr);
'lc^0'([], _Expr) -> [].</code>
+ <p>The compiler also understands that assigning to '_' means that
+ the value will not used. Therefore, the code in the following example
+ will also be optimized:</p>
+
+ <code type="erl"><![CDATA[
+_ = [io:put_chars(E) || E <- List],
+ok.]]></code>
+
</section>
<section>
@@ -209,11 +217,11 @@ some_function(...),
<section>
<title>Recursive List Functions</title>
- <p>In Section 7.2, the following myth was exposed:
+ <p>In section about myths, the following myth was exposed:
<seealso marker="myths#tail_recursive">Tail-Recursive Functions
are Much Faster Than Recursive Functions</seealso>.</p>
- <p>To summarize, in R12B there is usually not much difference between
+ <p>There is usually not much difference between
a body-recursive list function and tail-recursive function that reverses
the list at the end. Therefore, concentrate on writing beautiful code
and forget about the performance of your list functions. In the
diff --git a/system/doc/efficiency_guide/myths.xml b/system/doc/efficiency_guide/myths.xml
index 5d3ad78b23..778cd06c09 100644
--- a/system/doc/efficiency_guide/myths.xml
+++ b/system/doc/efficiency_guide/myths.xml
@@ -24,7 +24,7 @@
The Initial Developer of the Original Code is Ericsson AB.
</legalnotice>
- <title>The Eight Myths of Erlang Performance</title>
+ <title>The Seven Myths of Erlang Performance</title>
<prepared>Bjorn Gustavsson</prepared>
<docno></docno>
<date>2007-11-10</date>
@@ -35,80 +35,33 @@
<marker id="myths"></marker>
<p>Some truths seem to live on well beyond their best-before date,
perhaps because "information" spreads faster from person-to-person
- than a single release note that says, for example, that funs
- have become faster.</p>
+ than a single release note that says, for example, that body-recursive
+ calls have become faster.</p>
<p>This section tries to kill the old truths (or semi-truths) that have
become myths.</p>
<section>
- <title>Myth: Funs are Slow</title>
- <p>Funs used to be very slow, slower than <c>apply/3</c>.
- Originally, funs were implemented using nothing more than
- compiler trickery, ordinary tuples, <c>apply/3</c>, and a great
- deal of ingenuity.</p>
-
- <p>But that is history. Funs was given its own data type
- in R6B and was further optimized in R7B.
- Now the cost for a fun call falls roughly between the cost for a call
- to a local function and <c>apply/3</c>.</p>
- </section>
-
- <section>
- <title>Myth: List Comprehensions are Slow</title>
-
- <p>List comprehensions used to be implemented using funs, and in the
- old days funs were indeed slow.</p>
-
- <p>Nowadays, the compiler rewrites list comprehensions into an ordinary
- recursive function. Using a tail-recursive function with
- a reverse at the end would be still faster. Or would it?
- That leads us to the next myth.</p>
- </section>
-
- <section>
<title>Myth: Tail-Recursive Functions are Much Faster
Than Recursive Functions</title>
<p><marker id="tail_recursive"></marker>According to the myth,
- recursive functions leave references
- to dead terms on the stack and the garbage collector has to copy
- all those dead terms, while tail-recursive functions immediately
- discard those terms.</p>
-
- <p>That used to be true before R7B. In R7B, the compiler started
- to generate code that overwrites references to terms that will never
- be used with an empty list, so that the garbage collector would not
- keep dead values any longer than necessary.</p>
-
- <p>Even after that optimization, a tail-recursive function is
- still most of the times faster than a body-recursive function. Why?</p>
-
- <p>It has to do with how many words of stack that are used in each
- recursive call. In most cases, a recursive function uses more words
- on the stack for each recursion than the number of words a tail-recursive
- would allocate on the heap. As more memory is used, the garbage
- collector is invoked more frequently, and it has more work traversing
- the stack.</p>
-
- <p>In R12B and later releases, there is an optimization that
- in many cases reduces the number of words used on the stack in
- body-recursive calls. A body-recursive list function and a
- tail-recursive function that calls <seealso
- marker="stdlib:lists#reverse/1">lists:reverse/1</seealso> at
- the end will use the same amount of memory.
- <c>lists:map/2</c>, <c>lists:filter/2</c>, list comprehensions,
- and many other recursive functions now use the same amount of space
- as their tail-recursive equivalents.</p>
-
- <p>So, which is faster?
- It depends. On Solaris/Sparc, the body-recursive function seems to
- be slightly faster, even for lists with a lot of elements. On the x86
- architecture, tail-recursion was up to about 30% faster.</p>
-
- <p>So, the choice is now mostly a matter of taste. If you really do need
- the utmost speed, you must <em>measure</em>. You can no longer be
- sure that the tail-recursive list function always is the fastest.</p>
+ using a tail-recursive function that builds a list in reverse
+ followed by a call to <c>lists:reverse/1</c> is faster than
+ a body-recursive function that builds the list in correct order;
+ the reason being that body-recursive functions use more memory than
+ tail-recursive functions.</p>
+
+ <p>That was true to some extent before R12B. It was even more true
+ before R7B. Today, not so much. A body-recursive function
+ generally uses the same amount of memory as a tail-recursive
+ function. It is generally not possible to predict whether the
+ tail-recursive or the body-recursive version will be
+ faster. Therefore, use the version that makes your code cleaner
+ (hint: it is usually the body-recursive version).</p>
+
+ <p>For a more thorough discussion about tail and body recursion,
+ see <url href="http://ferd.ca/erlang-s-tail-recursion-is-not-a-silver-bullet.html">Erlang's Tail Recursion is Not a Silver Bullet</url>.</p>
<note><p>A tail-recursive function that does not need to reverse the
list at the end is faster than a body-recursive function,
@@ -199,6 +152,29 @@ vanilla_reverse([], Acc) ->
<p>That was once true, but from R6B the BEAM compiler can see
that a variable is not used.</p>
+
+ <p>Similarly, trivial transformations on the source-code level
+ such as converting a <c>case</c> statement to clauses at the
+ top-level of the function seldom makes any difference to the
+ generated code.</p>
+ </section>
+
+ <section>
+ <title>Myth: A NIF Always Speeds Up Your Program</title>
+
+ <p>Rewriting Erlang code to a NIF to make it faster should be
+ seen as a last resort. It is only guaranteed to be dangerous,
+ but not guaranteed to speed up the program.</p>
+
+ <p>Doing too much work in each NIF call will
+ <seealso marker="erts:erl_nif#WARNING">degrade responsiveness
+ of the VM</seealso>. Doing too little work may mean that
+ the gain of the faster processing in the NIF is eaten up by
+ the overhead of calling the NIF and checking the arguments.</p>
+
+ <p>Be sure to read about
+ <seealso marker="erts:erl_nif#lengthy_work">Long-running NIFs</seealso>
+ before writing a NIF.</p>
</section>
</chapter>
diff --git a/system/doc/efficiency_guide/part.xml b/system/doc/efficiency_guide/part.xml
index 6e10a0c031..5673ddd320 100644
--- a/system/doc/efficiency_guide/part.xml
+++ b/system/doc/efficiency_guide/part.xml
@@ -39,5 +39,6 @@
<xi:include href="drivers.xml"/>
<xi:include href="advanced.xml"/>
<xi:include href="profiling.xml"/>
+ <xi:include href="retired_myths.xml"/>
</part>
diff --git a/system/doc/efficiency_guide/processes.xml b/system/doc/efficiency_guide/processes.xml
index f2d9712f51..bc9daa6666 100644
--- a/system/doc/efficiency_guide/processes.xml
+++ b/system/doc/efficiency_guide/processes.xml
@@ -146,14 +146,14 @@ loop() ->
<section>
<title>Constant Pool</title>
- <p>Constant Erlang terms (also called <em>literals</em>) are now
+ <p>Constant Erlang terms (also called <em>literals</em>) are
kept in constant pools; each loaded module has its own pool.
- The following function does no longer build the tuple every time
+ The following function does not build the tuple every time
it is called (only to have it discarded the next time the garbage
collector was run), but the tuple is located in the module's
constant pool:</p>
- <p><em>DO</em> (in R12B and later)</p>
+ <p><em>DO</em></p>
<code type="erl">
days_in_month(M) ->
element(M, {31,28,31,30,31,30,31,31,30,31,30,31}).</code>
@@ -235,9 +235,7 @@ true
return the same value. Sharing has been lost.</p>
<p>In a future Erlang/OTP release, it might be implemented a
- way to (optionally) preserve sharing. There are no plans to make
- preserving of sharing the default behaviour, as that would
- penalize the vast majority of Erlang applications.</p>
+ way to (optionally) preserve sharing.</p>
</section>
</section>
diff --git a/system/doc/efficiency_guide/retired_myths.xml b/system/doc/efficiency_guide/retired_myths.xml
new file mode 100644
index 0000000000..37f46566cd
--- /dev/null
+++ b/system/doc/efficiency_guide/retired_myths.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>2016</year>
+ <year>2016</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.
+
+ The Initial Developer of the Original Code is Ericsson AB.
+ </legalnotice>
+ <marker id="retired_myths"/>
+ <title>Retired Myths</title>
+ <prepared>Bjorn Gustavsson</prepared>
+ <docno></docno>
+ <date>2016-06-07</date>
+ <rev></rev>
+ <file>retired_myths.xml</file>
+ </header>
+
+ <p>We belive that the truth finally has caught with the following,
+ retired myths.</p>
+
+ <section>
+ <title>Myth: Funs are Slow</title>
+ <p>Funs used to be very slow, slower than <c>apply/3</c>.
+ Originally, funs were implemented using nothing more than
+ compiler trickery, ordinary tuples, <c>apply/3</c>, and a great
+ deal of ingenuity.</p>
+
+ <p>But that is history. Funs was given its own data type
+ in R6B and was further optimized in R7B.
+ Now the cost for a fun call falls roughly between the cost for a call
+ to a local function and <c>apply/3</c>.</p>
+ </section>
+
+ <section>
+ <title>Myth: List Comprehensions are Slow</title>
+
+ <p>List comprehensions used to be implemented using funs, and in the
+ old days funs were indeed slow.</p>
+
+ <p>Nowadays, the compiler rewrites list comprehensions into an ordinary
+ recursive function. Using a tail-recursive function with
+ a reverse at the end would be still faster. Or would it?
+ That leads us to the myth that tail-recursive functions are faster
+ than body-recursive functions.</p>
+ </section>
+</chapter>
diff --git a/system/doc/reference_manual/character_set.xml b/system/doc/reference_manual/character_set.xml
index d25f2c001d..f0f4c23608 100644
--- a/system/doc/reference_manual/character_set.xml
+++ b/system/doc/reference_manual/character_set.xml
@@ -32,9 +32,9 @@
<section>
<title>Character Set</title>
- <p>Since Erlang 4.8/OTP R5A, the syntax of Erlang tokens is extended to
- allow the use of the full ISO-8859-1 (Latin-1) character set. This
- is noticeable in the following ways:</p>
+ <p>The syntax of Erlang tokens allow the use of the full
+ ISO-8859-1 (Latin-1) character set. This is noticeable in the
+ following ways:</p>
<list type="bulleted">
<item>
<p>All the Latin-1 printable characters can be used and are
diff --git a/system/doc/reference_manual/code_loading.xml b/system/doc/reference_manual/code_loading.xml
index f6fd2911fa..f5e5e74841 100644
--- a/system/doc/reference_manual/code_loading.xml
+++ b/system/doc/reference_manual/code_loading.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2003</year><year>2015</year>
+ <year>2003</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/system/doc/reference_manual/data_types.xml b/system/doc/reference_manual/data_types.xml
index e63825b97d..107e403903 100644
--- a/system/doc/reference_manual/data_types.xml
+++ b/system/doc/reference_manual/data_types.xml
@@ -50,10 +50,7 @@
<item><em><c>base</c></em><c>#</c><em><c>value</c></em> <br></br>
Integer with the base <em><c>base</c></em>, that must be an
- integer in the range 2..36. <br></br>
-
- In Erlang 5.2/OTP R9B and earlier versions, the allowed range
- is 2..16.</item>
+ integer in the range 2..36.</item>
</list>
<p><em>Examples:</em></p>
<pre>
diff --git a/system/doc/reference_manual/errors.xml b/system/doc/reference_manual/errors.xml
index e764cf431f..3e2d306561 100644
--- a/system/doc/reference_manual/errors.xml
+++ b/system/doc/reference_manual/errors.xml
@@ -49,8 +49,7 @@
The Erlang programming language has built-in features for
handling of run-time errors.</p>
<p>A run-time error can also be emulated by calling
- <c>erlang:error(Reason)</c> or <c>erlang:error(Reason, Args)</c>
- (those appeared in Erlang 5.4/OTP-R10).</p>
+ <c>erlang:error(Reason)</c> or <c>erlang:error(Reason, Args)</c>.</p>
<p>A run-time error is another name for an exception
of class <c>error</c>.
</p>
@@ -79,7 +78,6 @@
<p>Exceptions are run-time errors or generated errors and
are of three different classes, with different origins. The
<seealso marker="expressions#try">try</seealso> expression
- (new in Erlang 5.4/OTP R10B)
can distinguish between the different classes, whereas the
<seealso marker="expressions#catch">catch</seealso>
expression cannot. They are described in
@@ -94,7 +92,7 @@
<cell align="left" valign="middle"><c>error</c></cell>
<cell align="left" valign="middle">Run-time error,
for example, <c>1+a</c>, or the process called
- <c>erlang:error/1,2</c> (new in Erlang 5.4/OTP R10B)</cell>
+ <c>erlang:error/1,2</c></cell>
</row>
<row>
<cell align="left" valign="middle"><c>exit</c></cell>
@@ -111,7 +109,7 @@
and a stack trace (which aids in finding the code location of
the exception).</p>
<p>The stack trace can be retrieved using
- <c>erlang:get_stacktrace/0</c> (new in Erlang 5.4/OTP R10B)
+ <c>erlang:get_stacktrace/0</c>
from within a <c>try</c> expression, and is returned for
exceptions of class <c>error</c> from a <c>catch</c> expression.</p>
<p>An exception of class <c>error</c> is also known as a run-time
diff --git a/system/doc/reference_manual/expressions.xml b/system/doc/reference_manual/expressions.xml
index 1a3d19aed1..acd1dec901 100644
--- a/system/doc/reference_manual/expressions.xml
+++ b/system/doc/reference_manual/expressions.xml
@@ -123,10 +123,9 @@ member(_Elem, []) ->
or <c>receive</c> expression must be bound in all branches
to have a value outside the expression. Otherwise they
are regarded as 'unsafe' outside the expression.</p>
- <p>For the <c>try</c> expression introduced in
- Erlang 5.4/OTP R10B, variable scoping is limited so that
+ <p>For the <c>try</c> expression variable scoping is limited so that
variables bound in the expression are always 'unsafe' outside
- the expression. This is to be improved.</p>
+ the expression.</p>
</section>
<section>
@@ -189,7 +188,6 @@ f([$p,$r,$e,$f,$i,$x | Str]) -> ...</pre>
<pre>
case {Value, Result} of
{?THRESHOLD+1, ok} -> ...</pre>
- <p>This feature was added in Erlang 5.0/OTP R7.</p>
</section>
</section>
@@ -1348,8 +1346,8 @@ catch
ExceptionBodyN
end</code>
<p>This is an enhancement of
- <seealso marker="#catch">catch</seealso> that appeared in
- Erlang 5.4/OTP R10B. It gives the possibility to:</p>
+ <seealso marker="#catch">catch</seealso>.
+ It gives the possibility to:</p>
<list type="bulleted">
<item>Distinguish between different exception classes.</item>
<item>Choose to handle only the desired ones.</item>
diff --git a/system/doc/reference_manual/introduction.xml b/system/doc/reference_manual/introduction.xml
index abb4ed407d..5701462443 100644
--- a/system/doc/reference_manual/introduction.xml
+++ b/system/doc/reference_manual/introduction.xml
@@ -80,8 +80,8 @@
<item>A <em>list</em> is any number of items. For example,
an argument list can consist of zero, one, or more arguments.</item>
</list>
- <p>If a feature has been added recently, in Erlang 5.0/OTP R7 or
- later, this is mentioned in the text.</p>
+ <p>If a feature has been added in R13A or later,
+ this is mentioned in the text.</p>
</section>
<section>
diff --git a/system/doc/reference_manual/macros.xml b/system/doc/reference_manual/macros.xml
index 350bb1d123..b6c740dd10 100644
--- a/system/doc/reference_manual/macros.xml
+++ b/system/doc/reference_manual/macros.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2003</year><year>2015</year>
+ <year>2003</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -286,7 +286,6 @@ t.erl:5: Warning: -warning("Macro VERSION not defined -- using default version."
argument, is expanded to a string containing the tokens of
the argument. This is similar to the <c>#arg</c> stringifying
construction in C.</p>
- <p>The feature was added in Erlang 5.0/OTP R7.</p>
<p><em>Example:</em></p>
<code type="none">
-define(TESTCALL(Call), io:format("Call ~s: ~w~n", [??Call, Call])).
diff --git a/system/doc/reference_manual/records.xml b/system/doc/reference_manual/records.xml
index 12a3e697cd..1eb13b353e 100644
--- a/system/doc/reference_manual/records.xml
+++ b/system/doc/reference_manual/records.xml
@@ -72,9 +72,9 @@
<pre>
#Name{Field1=Expr1,...,FieldK=ExprK, _=ExprL}</pre>
<p>Omitted fields then get the value of evaluating <c>ExprL</c>
- instead of their default values. This feature was added in
- Erlang 5.1/OTP R8 and is primarily intended to be used to create
- patterns for ETS and Mnesia match functions.</p>
+ instead of their default values. This feature is primarily
+ intended to be used to create patterns for ETS and Mnesia match
+ functions.</p>
<p><em>Example:</em></p>
<pre>
-record(person, {name, phone, address}).
diff --git a/system/doc/reference_manual/typespec.xml b/system/doc/reference_manual/typespec.xml
index ced584ed35..a0ea41cb3b 100644
--- a/system/doc/reference_manual/typespec.xml
+++ b/system/doc/reference_manual/typespec.xml
@@ -11,7 +11,7 @@
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
@@ -63,7 +63,7 @@
Types consist of, and are built from, a set of predefined types,
for example, <c>integer()</c>, <c>atom()</c>, and <c>pid()</c>.
Predefined types represent a typically infinite set of Erlang terms that
- belong to this type. For example, the type <c>atom()</c> stands for the
+ belong to this type. For example, the type <c>atom()</c> denotes the
set of all Erlang atoms.
</p>
<p>
@@ -131,19 +131,19 @@
| nonempty_improper_list(Type1, Type2) %% Type1 and Type2 as above
| nonempty_list(Type) %% Proper non-empty list
- Map :: map() %% stands for a map of any size
- | #{} %% stands for the empty map
+ Map :: map() %% denotes a map of any size
+ | #{} %% denotes the empty map
| #{PairList}
- Tuple :: tuple() %% stands for a tuple of any size
+ Tuple :: tuple() %% denotes a tuple of any size
| {}
| {TList}
PairList :: Pair
| Pair, PairList
- Pair :: Type := Type %% denotes a pair that must be present
- | Type => Type
+ Pair :: Type := Type %% denotes a mandatory pair
+ | Type => Type %% denotes an optional pair
TList :: Type
| Type, TList
@@ -161,7 +161,7 @@
that <c>M</c> or <c>N</c>, or both, are zero.
</p>
<p>
- Because lists are commonly used, they have shorthand type notations.
+ Because lists are commonly used, they have shorthand type notations.
The types <c>list(T)</c> and <c>nonempty_list(T)</c> have the shorthands
<c>[T]</c> and <c>[T,...]</c>, respectively.
The only difference between the two shorthands is that <c>[T]</c> can be an
@@ -169,14 +169,18 @@
</p>
<p>
Notice that the shorthand for <c>list()</c>, that is, the list of
- elements of unknown type, is <c>[_]</c> (or <c>[any()]</c>), not <c>[]</c>.
+ elements of unknown type, is <c>[_]</c> (or <c>[any()]</c>), not <c>[]</c>.
The notation <c>[]</c> specifies the singleton type for the empty list.
</p>
<p>
The general form of maps is <c>#{PairList}</c>. The key types in
<c>PairList</c> are allowed to overlap, and if they do, the
leftmost pair takes precedence. A map pair has a key in
- <c>PairList</c> if it belongs to this type.
+ <c>PairList</c> if it belongs to this type. A <c>PairList</c> may contain
+ both 'mandatory' and 'optional' pairs where 'mandatory' denotes that
+ a key type, and its associated value type, must be present.
+ In the case of an 'optional' pair it is not required for the key type to
+ be present.
</p>
<p>
Notice that the syntactic representation of <c>map()</c> is
@@ -184,8 +188,8 @@
The notation <c>#{}</c> specifies the singleton type for the empty map.
</p>
<p>
- For convenience, the following types are also built-in.
- They can be thought as predefined aliases for the type unions also shown in
+ For convenience, the following types are also built-in.
+ They can be thought as predefined aliases for the type unions also shown in
the table.
</p>
<table>
@@ -201,37 +205,37 @@
<row>
<cell><c>bitstring()</c></cell><cell><c>&lt;&lt;_:_*1&gt;&gt;</c></cell>
</row>
- <row>
+ <row>
<cell><c>boolean()</c></cell><cell><c>'false' | 'true'</c></cell>
</row>
- <row>
+ <row>
<cell><c>byte()</c></cell><cell><c>0..255</c></cell>
</row>
<row>
<cell><c>char()</c></cell><cell><c>0..16#10ffff</c></cell>
</row>
- <row>
+ <row>
<cell><c>nil()</c></cell><cell><c>[]</c></cell>
</row>
<row>
<cell><c>number()</c></cell><cell><c>integer() | float()</c></cell>
</row>
- <row>
+ <row>
<cell><c>list()</c></cell><cell><c>[any()]</c></cell>
</row>
- <row>
+ <row>
<cell><c>maybe_improper_list()</c></cell><cell><c>maybe_improper_list(any(), any())</c></cell>
</row>
- <row>
+ <row>
<cell><c>nonempty_list()</c></cell><cell><c>nonempty_list(any())</c></cell>
</row>
<row>
<cell><c>string()</c></cell><cell><c>[char()]</c></cell>
</row>
- <row>
+ <row>
<cell><c>nonempty_string()</c></cell><cell><c>[char(),...]</c></cell>
</row>
- <row>
+ <row>
<cell><c>iodata()</c></cell><cell><c>iolist() | binary()</c></cell>
</row>
<row>
@@ -243,7 +247,7 @@
<row>
<cell><c>module()</c></cell><cell><c>atom()</c></cell>
</row>
- <row>
+ <row>
<cell><c>mfa()</c></cell><cell><c>{module(),atom(),arity()}</c></cell>
</row>
<row>
@@ -259,7 +263,7 @@
<cell><c>timeout()</c></cell><cell><c>'infinity' | non_neg_integer()</c></cell>
</row>
<row>
- <cell><c>no_return()</c></cell><cell><c>none()</c></cell>
+ <cell><c>no_return()</c></cell><cell><c>none()</c></cell>
</row>
<tcaption>Built-in types, predefined aliases</tcaption>
</table>
@@ -284,11 +288,11 @@
</row>
<tcaption>Additional built-in types</tcaption>
</table>
-
+
<p>
Users are not allowed to define types with the same names as the
predefined or built-in ones. This is checked by the compiler and
- its violation results in a compilation error.
+ its violation results in a compilation error.
</p>
<note>
<p>
@@ -394,13 +398,13 @@
<pre>
-record(rec, {field1 :: Type1, field2, field3 :: Type3}).</pre>
<p>
- For fields without type annotations, their type defaults to any().
+ For fields without type annotations, their type defaults to any().
That is, the previous example is a shorthand for the following:
</p>
<pre>
-record(rec, {field1 :: Type1, field2 :: any(), field3 :: Type3}).</pre>
<p>
- In the presence of initial values for fields,
+ In the presence of initial values for fields,
the type must be declared after the initialization, as follows:
</p>
<pre>
@@ -409,12 +413,12 @@
The initial values for fields are to be compatible
with (that is, a member of) the corresponding types.
This is checked by the compiler and results in a compilation error
- if a violation is detected.
+ if a violation is detected.
</p>
<note>
<p>Before Erlang/OTP 19, for fields without initial values,
the singleton type <c>'undefined'</c> was added to all declared types.
- In other words, the following two record declarations had identical
+ In other words, the following two record declarations had identical
effects:</p>
<pre>
-record(rec, {f1 = 42 :: integer(),
@@ -430,22 +434,22 @@
</p>
</note>
<p>
- Any record, containing type information or not, once defined,
+ Any record, containing type information or not, once defined,
can be used as a type using the following syntax:
</p>
<pre> #rec{}</pre>
<p>
- In addition, the record fields can be further specified when using
+ In addition, the record fields can be further specified when using
a record type by adding type information about the field
as follows:
</p>
<pre> #rec{some_field :: Type}</pre>
<p>
- Any unspecified fields are assumed to have the type in the original
+ Any unspecified fields are assumed to have the type in the original
record declaration.
</p>
</section>
-
+
<section>
<title>Specifications for Functions</title>
<p>
@@ -459,9 +463,9 @@
else a compilation error occurs.
</p>
<p>
- This form can also be used in header files (.hrl) to declare type
- information for exported functions.
- Then these header files can be included in files that (implicitly or
+ This form can also be used in header files (.hrl) to declare type
+ information for exported functions.
+ Then these header files can be included in files that (implicitly or
explicitly) import these functions.
</p>
<p>
@@ -475,14 +479,14 @@
<pre>
-spec Function(ArgName1 :: Type1, ..., ArgNameN :: TypeN) -> RT.</pre>
<p>
- A function specification can be overloaded.
+ A function specification can be overloaded.
That is, it can have several types, separated by a semicolon (<c>;</c>):
</p>
<pre>
-spec foo(T1, T2) -> T3
; (T4, T5) -> T6.</pre>
<p>
- A current restriction, which currently results in a warning
+ A current restriction, which currently results in a warning
(not an error) by the compiler, is that the domains of
the argument types cannot overlap.
For example, the following specification results in a warning:
@@ -491,9 +495,9 @@
-spec foo(pos_integer()) -> pos_integer()
; (integer()) -> integer().</pre>
<p>
- Type variables can be used in specifications to specify relations for
- the input and output arguments of a function.
- For example, the following specification defines the type of a
+ Type variables can be used in specifications to specify relations for
+ the input and output arguments of a function.
+ For example, the following specification defines the type of a
polymorphic identity function:
</p>
<pre>
@@ -542,8 +546,8 @@
-spec foo({X, integer()}) -> X when X :: atom()
; ([Y]) -> Y when Y :: number().</pre>
<p>
- Some functions in Erlang are not meant to return;
- either because they define servers or because they are used to
+ Some functions in Erlang are not meant to return;
+ either because they define servers or because they are used to
throw exceptions, as in the following function:
</p>
<pre> my_error(Err) -> erlang:throw({error, Err}).</pre>
@@ -555,4 +559,3 @@
<pre> -spec my_error(term()) -> no_return().</pre>
</section>
</chapter>
-
diff --git a/system/doc/tutorial/c_port.xmlsrc b/system/doc/tutorial/c_port.xmlsrc
index 3c3bc48044..ff0997fb54 100644
--- a/system/doc/tutorial/c_port.xmlsrc
+++ b/system/doc/tutorial/c_port.xmlsrc
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2000</year><year>2015</year>
+ <year>2000</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/system/doc/tutorial/c_portdriver.xmlsrc b/system/doc/tutorial/c_portdriver.xmlsrc
index 933e2395a3..da680642b6 100644
--- a/system/doc/tutorial/c_portdriver.xmlsrc
+++ b/system/doc/tutorial/c_portdriver.xmlsrc
@@ -161,8 +161,8 @@ decode([Int]) -> Int.</pre>
<title>Running the Example</title>
<p><em>Step 1.</em> Compile the C code:</p>
<pre>
-unix> <input>gcc -o exampledrv -fpic -shared complex.c port_driver.c</input>
-windows> <input>cl -LD -MD -Fe exampledrv.dll complex.c port_driver.c</input></pre>
+unix> <input>gcc -o example_drv.so -fpic -shared complex.c port_driver.c</input>
+windows> <input>cl -LD -MD -Fe example_drv.dll complex.c port_driver.c</input></pre>
<p><em>Step 2.</em> Start Erlang and compile the Erlang code:</p>
<pre>
> <input>erl</input>