<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">

<head>
<meta http-equiv=Content-Type content="text/html; charset=us-ascii">
<meta name=Generator content="Microsoft Word 12 (filtered medium)">
<style>
<!--
 /* Font Definitions */
 @font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
 /* Style Definitions */
 p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0cm;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri","sans-serif";}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:purple;
        text-decoration:underline;}
span.E-postmall17
        {mso-style-type:personal-compose;
        font-family:"Calibri","sans-serif";
        color:windowtext;}
.MsoChpDefault
        {mso-style-type:export-only;}
@page Section1
        {size:612.0pt 792.0pt;
        margin:70.85pt 70.85pt 70.85pt 70.85pt;}
div.Section1
        {page:Section1;}
-->
</style>
<!--[if gte mso 9]><xml>
 <o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
 <o:shapelayout v:ext="edit">
  <o:idmap v:ext="edit" data="1" />
 </o:shapelayout></xml><![endif]-->
</head>

<body lang=SV link=blue vlink=purple>

<div class=Section1>

<p class=MsoNormal><span lang=EN-GB>Try running hog:main() in the program
below. It creates a data structure in one process, measuring heap size, and how
it changes during the creation. Then it sends it to another, measuring the memory
allocated in the receiving process. Here’s the output:<o:p></o:p></span></p>

<p class=MsoNormal><span lang=EN-GB><o:p> </o:p></span></p>

<p class=MsoNormal><span lang=EN-GB>Creating tree:: allocated 0 bytes, heap
size 987 bytes<o:p></o:p></span></p>

<p class=MsoNormal><span lang=EN-GB>Receiving tree:: allocated 116769407 bytes,
heap size 116769640 bytes<o:p></o:p></span></p>

<p class=MsoNormal><span lang=EN-GB>true<o:p></o:p></span></p>

<p class=MsoNormal><span lang=EN-GB><o:p> </o:p></span></p>

<p class=MsoNormal><span lang=EN-GB>That is, the structure is less than 1K
bytes in the sender, but over 100MB in the receiver.<o:p></o:p></span></p>

<p class=MsoNormal><span lang=EN-GB><o:p> </o:p></span></p>

<p class=MsoNormal><span lang=EN-GB>The reason is that it contains  a lot
of sharing, and sharing is lost when messages are sent to other processes. Sharing
is ALSO lost when values are copied to a new process being spawned. In fact, I’ve
found no way to copy structures between processes WITHOUT losing sharing. This
means that some data simply cannot practically be sent from one process to
another.<o:p></o:p></span></p>

<p class=MsoNormal><span lang=EN-GB><o:p> </o:p></span></p>

<p class=MsoNormal><span lang=EN-GB>I understand, of course, that if I send the
same structure IN TWO SEPARATE MESSAGES, that I am bound to get two copies in
the receiver. But if I send a structure in  ONE message, then there’s
in principle no reason why the copy could not preserve sharing. That’s
true even when copying between nodes.<o:p></o:p></span></p>

<p class=MsoNormal><span lang=EN-GB><o:p> </o:p></span></p>

<p class=MsoNormal><span lang=EN-GB>In my real application the data is funs,
constructed in a complex manner so that I cannot predict the sharing. When the
sharing is lost, they get bigger than the tree in my example. If I can’t
preserve sharing when I send them to another process, then I can’t
structure my program using processes. That, in turn, limits my ability to trap
exits.<o:p></o:p></span></p>

<p class=MsoNormal><span lang=EN-GB><o:p> </o:p></span></p>

<p class=MsoNormal><span lang=EN-GB>Any chance of introducing a sharing-preserving
copy in message send and spawn? It would be really useful!<o:p></o:p></span></p>

<p class=MsoNormal><span lang=EN-GB><o:p> </o:p></span></p>

<p class=MsoNormal><span lang=EN-GB>John Hughes<o:p></o:p></span></p>

<p class=MsoNormal><span lang=EN-GB><o:p> </o:p></span></p>

<p class=MsoNormal><span lang=EN-GB><o:p> </o:p></span></p>

<p class=MsoNormal><span lang=EN-GB>-module(hog).<o:p></o:p></span></p>

<p class=MsoNormal><span lang=EN-GB>-compile(export_all).<o:p></o:p></span></p>

<p class=MsoNormal><span lang=EN-GB><o:p> </o:p></span></p>

<p class=MsoNormal><span lang=EN-GB>% Builds a binary tree of depth N. Note the
sharing!<o:p></o:p></span></p>

<p class=MsoNormal><span lang=EN-GB>tree(0) -><o:p></o:p></span></p>

<p class=MsoNormal><span lang=EN-GB>    leaf;<o:p></o:p></span></p>

<p class=MsoNormal><span lang=EN-GB>tree(N) -> <o:p></o:p></span></p>

<p class=MsoNormal><span lang=EN-GB>    T = tree(N-1),<o:p></o:p></span></p>

<p class=MsoNormal><span lang=EN-GB>    {T,T}.<o:p></o:p></span></p>

<p class=MsoNormal><span lang=EN-GB><o:p> </o:p></span></p>

<p class=MsoNormal><span lang=EN-GB>measure(S,F) -><o:p></o:p></span></p>

<p class=MsoNormal><span lang=EN-GB>    {heap_size,Before} =
process_info(self(),heap_size),<o:p></o:p></span></p>

<p class=MsoNormal><span lang=EN-GB>    Result = F(),<o:p></o:p></span></p>

<p class=MsoNormal><span lang=EN-GB>    {heap_size,After} =
process_info(self(),heap_size),<o:p></o:p></span></p>

<p class=MsoNormal><span lang=EN-GB>    io:format("~s:
allocated ~w bytes, heap size ~w bytes~n",<o:p></o:p></span></p>

<p class=MsoNormal><span lang=EN-GB>                                  
[S,After-Before,After]),<o:p></o:p></span></p>

<p class=MsoNormal><span lang=EN-GB>    Result.<o:p></o:p></span></p>

<p class=MsoNormal><span lang=EN-GB><o:p> </o:p></span></p>

<p class=MsoNormal><span lang=EN-GB>main() -><o:p></o:p></span></p>

<p class=MsoNormal><span lang=EN-GB>    T =
measure("Creating tree:",fun() -> tree(25) end),<o:p></o:p></span></p>

<p class=MsoNormal><span lang=EN-GB>    Child = spawn(fun()
-> child() end),<o:p></o:p></span></p>

<p class=MsoNormal><span lang=EN-GB>    erlang:yield(),<o:p></o:p></span></p>

<p class=MsoNormal><span lang=EN-GB>    Child ! T,<o:p></o:p></span></p>

<p class=MsoNormal><span lang=EN-GB>    erlang:yield().<o:p></o:p></span></p>

<p class=MsoNormal><span lang=EN-GB><o:p> </o:p></span></p>

<p class=MsoNormal><span lang=EN-GB>child() -><o:p></o:p></span></p>

<p class=MsoNormal><span lang=EN-GB>    measure("Receiving
tree:",fun() -> receive Tree -> ok end end).<o:p></o:p></span></p>

<p class=MsoNormal><span lang=EN-GB>                                                                                                                         
<o:p></o:p></span></p>

</div>

</body>

</html>