Sophie

Sophie

distrib > Fedora > 17 > i386 > media > updates > by-pkgid > 675c8c8167236dfcf8d66da674f931e8 > files > 46

erlang-doc-R15B-03.3.fc17.noarch.rpm

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html xmlns:fn="http://www.w3.org/2005/02/xpath-functions">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" href="../otp_doc.css" type="text/css">
<title>Erlang -- Common Caveats</title>
</head>
<body bgcolor="white" text="#000000" link="#0000ff" vlink="#ff00ff" alink="#ff0000"><div id="container">
<script id="js" type="text/javascript" language="JavaScript" src="../js/flipmenu/flipmenu.js"></script><script id="js2" type="text/javascript" src="../js/erlresolvelinks.js"></script><script language="JavaScript" type="text/javascript">
            <!--
              function getWinHeight() {
                var myHeight = 0;
                if( typeof( window.innerHeight ) == 'number' ) {
                  //Non-IE
                  myHeight = window.innerHeight;
                } else if( document.documentElement && ( document.documentElement.clientWidth ||
                                                         document.documentElement.clientHeight ) ) {
                  //IE 6+ in 'standards compliant mode'
                  myHeight = document.documentElement.clientHeight;
                } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
                  //IE 4 compatible
                  myHeight = document.body.clientHeight;
                }
                return myHeight;
              }

              function setscrollpos() {
                var objf=document.getElementById('loadscrollpos');
                 document.getElementById("leftnav").scrollTop = objf.offsetTop - getWinHeight()/2;
              }

              function addEvent(obj, evType, fn){
                if (obj.addEventListener){
                obj.addEventListener(evType, fn, true);
                return true;
              } else if (obj.attachEvent){
                var r = obj.attachEvent("on"+evType, fn);
                return r;
              } else {
                return false;
              }
             }

             addEvent(window, 'load', setscrollpos);

             //--></script><div id="leftnav"><div class="innertube">
<img alt="Erlang logo" src="../erlang-logo.png"><br><small><a href="users_guide.html">User's Guide</a><br><a href="../pdf/otp-system-documentation-5.9.3.1.pdf">PDF</a><br><a href="../index.html">Top</a></small><p><strong>Efficiency Guide</strong><br><strong>User's Guide</strong><br><small>Version 5.9.3.1</small></p>
<br><a href="javascript:openAllFlips()">Expand All</a><br><a href="javascript:closeAllFlips()">Contract All</a><p><small><strong>Chapters</strong></small></p>
<ul class="flipMenu" imagepath="../js/flipmenu">
<li id="no" title="Introduction" expanded="false">Introduction<ul>
<li><a href="introduction.html">
              Top of chapter
            </a></li>
<li title="Purpose"><a href="introduction.html#id62954">Purpose</a></li>
<li title="Prerequisites"><a href="introduction.html#id65420">Prerequisites</a></li>
</ul>
</li>
<li id="no" title="The Eight Myths of Erlang Performance" expanded="false">The Eight Myths of Erlang Performance<ul>
<li><a href="myths.html">
              Top of chapter
            </a></li>
<li title="Myth: Funs are slow"><a href="myths.html#id64448">Myth: Funs are slow</a></li>
<li title="Myth: List comprehensions are slow"><a href="myths.html#id61406">Myth: List comprehensions are slow</a></li>
<li title="Myth: Tail-recursive functions are MUCH faster
    than recursive functions"><a href="myths.html#id62291">Myth: Tail-recursive functions are MUCH faster
    than recursive functions</a></li>
<li title="Myth: '++' is always bad"><a href="myths.html#id60058">Myth: '++' is always bad</a></li>
<li title="Myth: Strings are slow"><a href="myths.html#id62534">Myth: Strings are slow</a></li>
<li title="Myth: Repairing a Dets file is very slow"><a href="myths.html#id61135">Myth: Repairing a Dets file is very slow</a></li>
<li title="Myth: BEAM is a stack-based byte-code virtual machine (and therefore slow)"><a href="myths.html#id64006">Myth: BEAM is a stack-based byte-code virtual machine (and therefore slow)</a></li>
<li title="Myth: Use '_' to speed up your program when a variable is not used"><a href="myths.html#id64026">Myth: Use '_' to speed up your program when a variable is not used</a></li>
</ul>
</li>
<li id="loadscrollpos" title="Common Caveats" expanded="true">Common Caveats<ul>
<li><a href="commoncaveats.html">
              Top of chapter
            </a></li>
<li title="The timer module"><a href="commoncaveats.html#id62547">The timer module</a></li>
<li title="list_to_atom/1"><a href="commoncaveats.html#id61885">list_to_atom/1</a></li>
<li title="length/1"><a href="commoncaveats.html#id60806">length/1</a></li>
<li title="setelement/3"><a href="commoncaveats.html#id58300">setelement/3</a></li>
<li title="size/1"><a href="commoncaveats.html#id65402">size/1</a></li>
<li title="split_binary/2"><a href="commoncaveats.html#id60836">split_binary/2</a></li>
<li title="The '--' operator"><a href="commoncaveats.html#id61766">The '--' operator</a></li>
</ul>
</li>
<li id="no" title="Constructing and matching binaries" expanded="false">Constructing and matching binaries<ul>
<li><a href="binaryhandling.html">
              Top of chapter
            </a></li>
<li title="How binaries are implemented"><a href="binaryhandling.html#id62932">How binaries are implemented</a></li>
<li title="Constructing binaries"><a href="binaryhandling.html#id66066">Constructing binaries</a></li>
<li title="Matching binaries"><a href="binaryhandling.html#id63610">Matching binaries</a></li>
</ul>
</li>
<li id="no" title="List handling" expanded="false">List handling<ul>
<li><a href="listHandling.html">
              Top of chapter
            </a></li>
<li title="Creating a list"><a href="listHandling.html#id66709">Creating a list</a></li>
<li title="List comprehensions"><a href="listHandling.html#id66805">List comprehensions</a></li>
<li title="Deep and flat lists"><a href="listHandling.html#id66875">Deep and flat lists</a></li>
<li title="Why you should not worry about recursive lists functions"><a href="listHandling.html#id67017">Why you should not worry about recursive lists functions</a></li>
</ul>
</li>
<li id="no" title="Functions" expanded="false">Functions<ul>
<li><a href="functions.html">
              Top of chapter
            </a></li>
<li title="Pattern matching"><a href="functions.html#id67142">Pattern matching</a></li>
<li title="Function Calls "><a href="functions.html#id67362">Function Calls </a></li>
<li title="Memory usage in recursion"><a href="functions.html#id67506">Memory usage in recursion</a></li>
</ul>
</li>
<li id="no" title="Tables and databases" expanded="false">Tables and databases<ul>
<li><a href="tablesDatabases.html">
              Top of chapter
            </a></li>
<li title="Ets, Dets and Mnesia"><a href="tablesDatabases.html#id67596">Ets, Dets and Mnesia</a></li>
<li title="Ets specific"><a href="tablesDatabases.html#id67983">Ets specific</a></li>
<li title="Mnesia specific"><a href="tablesDatabases.html#id68087">Mnesia specific</a></li>
</ul>
</li>
<li id="no" title="Processes" expanded="false">Processes<ul>
<li><a href="processes.html">
              Top of chapter
            </a></li>
<li title="Creation of an Erlang process"><a href="processes.html#id68191">Creation of an Erlang process</a></li>
<li title="Process messages"><a href="processes.html#id68339">Process messages</a></li>
<li title="The SMP emulator"><a href="processes.html#id68531">The SMP emulator</a></li>
</ul>
</li>
<li id="no" title="Drivers" expanded="false">Drivers<ul>
<li><a href="drivers.html">
              Top of chapter
            </a></li>
<li title="Drivers and concurrency"><a href="drivers.html#id68634">Drivers and concurrency</a></li>
<li title="Avoiding copying of binaries when calling a driver"><a href="drivers.html#id68675">Avoiding copying of binaries when calling a driver</a></li>
<li title="Returning small binaries from a driver"><a href="drivers.html#id68743">Returning small binaries from a driver</a></li>
<li title="Returning big binaries without copying from a driver"><a href="drivers.html#id68777">Returning big binaries without copying from a driver</a></li>
</ul>
</li>
<li id="no" title="Advanced" expanded="false">Advanced<ul>
<li><a href="advanced.html">
              Top of chapter
            </a></li>
<li title="Memory"><a href="advanced.html#id68919">Memory</a></li>
<li title="System limits"><a href="advanced.html#id69276">System limits</a></li>
</ul>
</li>
<li id="no" title="Profiling" expanded="false">Profiling<ul>
<li><a href="profiling.html">
              Top of chapter
            </a></li>
<li title="Do not guess about performance - profile"><a href="profiling.html#id69579">Do not guess about performance - profile</a></li>
<li title="Big systems"><a href="profiling.html#id69661">Big systems</a></li>
<li title="What to look for"><a href="profiling.html#id69681">What to look for</a></li>
<li title="Tools"><a href="profiling.html#id69738">Tools</a></li>
<li title="Benchmarking"><a href="profiling.html#id70245">Benchmarking</a></li>
</ul>
</li>
</ul>
</div></div>
<div id="content">
<div class="innertube">
<h1>3 Common Caveats</h1>
  

  <p>Here we list a few modules and BIFs to watch out for, and not only
  from a performance point of view.</p>

  <h3><a name="id62547">3.1 
        The timer module</a></h3>
     

     <p>Creating timers using <span class="bold_code"><a href="javascript:erlhref('../../','erts','erlang.html#erlang:send_after-3');">erlang:send_after/3</a></span>
     and <span class="bold_code"><a href="javascript:erlhref('../../','erts','erlang.html#erlang:start_timer-3');">erlang:start_timer/3</a></span>
     is much more efficient than using the timers provided by the
     <span class="bold_code"><a href="javascript:erlhref('../../','stdlib','timer.html');">timer</a></span> module. The
     <span class="code">timer</span> module uses a separate process to manage the timers,
     and that process can easily become overloaded if many processes
     create and cancel timers frequently (especially when using the
     SMP emulator).</p>

     <p>The functions in the <span class="code">timer</span> module that do not manage timers (such as
     <span class="code">timer:tc/3</span> or <span class="code">timer:sleep/1</span>), do not call the timer-server process
     and are therefore harmless.</p>
  

  <h3><a name="id61885">3.2 
        list_to_atom/1</a></h3>
    

    <p>Atoms are not garbage-collected. Once an atom is created, it will never
    be removed. The emulator will terminate if the limit for the number
    of atoms (1048576 by default) is reached.</p>

    <p>Therefore, converting arbitrary input strings to atoms could be
    dangerous in a system that will run continuously.
    If only certain well-defined atoms are allowed as input, you can use
    <span class="bold_code"><a href="javascript:erlhref('../../','erts','erlang.html#list_to_existing_atom-1');">list_to_existing_atom/1</a></span>
    to guard against a denial-of-service attack. (All atoms that are allowed
    must have been created earlier, for instance by simply using all of them
    in a module and loading that module.)</p>

    <p>Using <span class="code">list_to_atom/1</span> to construct an atom that is passed to
    <span class="code">apply/3</span> like this</p>

    <div class="example"><pre>
apply(list_to_atom("some_prefix"++Var), foo, Args)</pre></div>    

    <p>is quite expensive and is not recommended in time-critical code.</p>
  

  <h3><a name="id60806">3.3 
        length/1</a></h3>
    

    <p>The time for calculating the length of a list is proportional to the
    length of the list, as opposed to <span class="code">tuple_size/1</span>, <span class="code">byte_size/1</span>,
    and <span class="code">bit_size/1</span>, which all execute in constant time.</p>

    <p>Normally you don't have to worry about the speed of <span class="code">length/1</span>,
    because it is efficiently implemented in C. In time critical-code, though,
    you might want to avoid it if the input list could potentially be very long.</p>

    <p>Some uses of <span class="code">length/1</span> can be replaced by matching.
    For instance, this code</p>

    <div class="example"><pre>
foo(L) when length(L) &gt;= 3 -&gt;
    ...</pre></div>    

    <p>can be rewritten to</p>
    <div class="example"><pre>
foo([_,_,_|_]=L) -&gt;
   ...</pre></div>    

   <p>(One slight difference is that <span class="code">length(L)</span> will fail if the <span class="code">L</span>
   is an improper list, while the pattern in the second code fragment will
   accept an improper list.)</p>
  

  <h3><a name="id58300">3.4 
        setelement/3</a></h3>
    

    <p><span class="bold_code"><a href="javascript:erlhref('../../','erts','erlang.html#setelement-3');">setelement/3</a></span>
    copies the tuple it modifies. Therefore, updating a tuple in a loop
    using <span class="code">setelement/3</span> will create a new copy of the tuple every time.</p>
    
    <p>There is one exception to the rule that the tuple is copied.
    If the compiler clearly can see that destructively updating the tuple would
    give exactly the same result as if the tuple was copied, the call to
    <span class="code">setelement/3</span> will be replaced with a special destructive setelement
    instruction. In the following code sequence</p>

    <div class="example"><pre>
multiple_setelement(T0) -&gt;
    T1 = setelement(9, T0, bar),
    T2 = setelement(7, T1, foobar),
    setelement(5, T2, new_value).</pre></div>    

    <p>the first <span class="code">setelement/3</span> call will copy the tuple and modify the
    ninth element. The two following <span class="code">setelement/3</span> calls will modify
    the tuple in place.</p>

    <p>For the optimization to be applied, <strong>all</strong> of the followings conditions
    must be true:</p>

    <ul>
    <li>The indices must be integer literals, not variables or expressions.</li>
    <li>The indices must be given in descending order.</li>
    <li>There must be no calls to other function in between the calls to
    <span class="code">setelement/3</span>.</li>
    <li>The tuple returned from one <span class="code">setelement/3</span> call must only be used
    in the subsequent call to <span class="code">setelement/3</span>.</li>
    </ul>

    <p>If it is not possible to structure the code as in the <span class="code">multiple_setelement/1</span>
    example, the best way to modify multiple elements in a large tuple is to
    convert the tuple to a list, modify the list, and convert the list back to
    a tuple.</p>
  

  <h3><a name="id65402">3.5 
        size/1</a></h3>
    

    <p><span class="code">size/1</span> returns the size for both tuples and binary.</p>

    <p>Using the new BIFs <span class="code">tuple_size/1</span> and <span class="code">byte_size/1</span> introduced
    in R12B gives the compiler and run-time system more opportunities for
    optimization. A further advantage is that the new BIFs could help Dialyzer
    find more bugs in your program.</p>
  

  <h3><a name="id60836">3.6 
        split_binary/2</a></h3>
    
      <p>It is usually more efficient to split a binary using matching
      instead of calling the <span class="code">split_binary/2</span> function.
      Furthermore, mixing bit syntax matching and <span class="code">split_binary/2</span>
      may prevent some optimizations of bit syntax matching.</p>

        <p><strong>DO</strong></p>
        <div class="example"><pre>
        &lt;&lt;Bin1:Num/binary,Bin2/binary&gt;&gt; = Bin,</pre></div>
        <p><strong>DO NOT</strong></p>
        <div class="example"><pre>
        {Bin1,Bin2} = split_binary(Bin, Num)
        </pre></div>
   

  <h3><a name="id61766">3.7 
        The '--' operator</a></h3>
    
     <p>Note that the '<span class="code">--</span>' operator has a complexity
     proportional to the product of the length of its operands,
     meaning that it will be very slow if both of its operands
     are long lists:</p>

        <p><strong>DO NOT</strong></p>
        <div class="example"><pre>
        HugeList1 -- HugeList2</pre></div>

     <p>Instead use the <span class="bold_code"><a href="javascript:erlhref('../../','stdlib','ordsets.html');">ordsets</a></span>
     module:</p>

        <p><strong>DO</strong></p>
        <div class="example"><pre>
        HugeSet1 = ordsets:from_list(HugeList1),
        HugeSet2 = ordsets:from_list(HugeList2),
        ordsets:subtract(HugeSet1, HugeSet2)
        </pre></div>

     <p>Obviously, that code will not work if the original order
     of the list is important. If the order of the list must be
     preserved, do like this:</p>

        <p><strong>DO</strong></p>
        <div class="example"><pre>
        Set = gb_sets:from_list(HugeList2),
        [E || E &lt;- HugeList1, not gb_sets:is_element(E, Set)]</pre></div>

     <p>Subtle note 1: This code behaves differently from '<span class="code">--</span>'
     if the lists contain duplicate elements. (One occurrence
     of an element in HugeList2 will remove <strong>all</strong>
     occurrences in HugeList1.)</p>

     <p>Subtle note 2: This code compares lists elements using the
     '<span class="code">==</span>' operator, while '<span class="code">--</span>' uses the '<span class="code">=:=</span>'. If
     that difference is important, <span class="code">sets</span> can be used instead of
     <span class="code">gb_sets</span>, but note that <span class="code">sets:from_list/1</span> is much
     slower than <span class="code">gb_sets:from_list/1</span> for long lists.</p>

     <p>Using the '<span class="code">--</span>' operator to delete an element
     from a list is not a performance problem:</p>

        <p><strong>OK</strong></p>
        <div class="example"><pre>
        HugeList1 -- [Element]
        </pre></div>

   

</div>
<div class="footer">
<hr>
<p>Copyright © 2001-2012 Ericsson AB. All Rights Reserved.</p>
</div>
</div>
</div></body>
</html>