<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="314212" data-post-id="314212">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="andzdroid" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/andzdroid/120/31831_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  andzdroid
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Thank you for the detailed explanation!</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="314212" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/question-about-memory-copy/60905/12">Post #11</a>
	                </div>
	            </div>
              <div id="likers-container-314212" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="314212"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #11"></div>
  </section>
</div>
    <div class="postbit" id="314261" data-post-id="314261">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="lucaong" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/lucaong/120/21794_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  lucaong
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Also, more clarifications regarding <a class="mention" href="/u/joey_the_snake" rel="nofollow">@joey_the_snake</a> replies:</p>
<blockquote>
<p>If it was a pointer or a reference then it wouldn’t really be a snapshot because then you could see other people’s modifications. Otherwise it would have to be a pointer or a reference to a copy.</p>
</blockquote>
<p>No: it is a reference to the original data, a simple pointer, but it is isolated from other updates. The trick is that the original data is immutable, it cannot be changed by other updates. Instead, updates create a new Btree root that points to all the data that did not change, plus the part that changed. It is the same principle underlying immutable data structures with structural sharing (like those in Elixir, Clojure, etc.)</p>
<blockquote>
<p>Looking at the source, it seems like a tree structure is copied to the caller. And this tree structure is walked when trying to read particular keys.</p>
</blockquote>
<p>Not the whole tree, just the root, which is a small data structure. And yes, the tree is walked when accessed, but it is not a copy: it is the original (immutable) tree, but accessed from the snapshot root.</p>
<blockquote>
<p>Yeah true. I do see the OP’s point though. I wouldn’t necessarily expect the full tree structure, even if it doesn’t have all the data, based on the description.</p>
</blockquote>
<p>It’s not the full tree. You can think about it with an analogy with Elixir immutable data structures:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir"># Say we have a map, which in our analogy is the database
m = %{ foo: 1, bar: 2, baz: [1, 2, 3] }

# I take a "snapshot" by saving a reference to the current map
s = m

# Note that nothing was copied above. Simply, a new reference to the
# same (immutable) data structure is created

# This "snapshot" is isolated from changes:
m = Map.put(m, :bar, 3)
m # =&gt; %{ foo: 1, bar: 3, baz: [1, 2, 3] }
s # =&gt; %{ foo: 1, bar: 2, baz: [1, 2, 3] }
</code></pre>
<p>Note the part that is in common between <code>s</code> and <code>m</code> was not copied: both <code>s</code> and <code>m</code> point to the same values (for example the key <code>:baz</code> points to the same list in <code>m</code> and <code>s</code>, <strong>not</strong> to two identical copies). Yet, because maps are immutable in Elixir, <code>s</code> does not see changes. Simply, <code>m</code> tracks the latest updates, while <code>s</code> keeps pointing to a certain version.</p>
<p>As soon as <code>s</code> is not in scope anymore, the garbage collector can then clean up the old data that is not reachable anymore from <code>m</code>.</p>
<p><code>CubDB</code> works in much the same way, just on disk instead than in memory, and therefore with some different implementation details to account for the difference performance characteristics of disk vs. memory.</p>
<p>I just found <a href="https://www.bzero.se/ldapd/btree.html" rel="noopener nofollow ugc">this nice explanation of how an append-only Btree works</a>, which corresponds to how <code>CubDB</code> works internally. On top of that, <code>CubDB</code> uses a compaction process to “garbage collect” disk space and avoid growing indefinitely with each update.</p>
<p>I hope this clarifies it further <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="314261" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/question-about-memory-copy/60905/13">Post #12</a>
	                </div>
	            </div>
              <div id="likers-container-314261" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="314261"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #12"></div>
  </section>
</div>
    <div class="postbit" id="314263" data-post-id="314263">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="joey_the_snake" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  joey_the_snake
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Thank you for the explanations you’ve provided in this thread. What you’ve created is really interesting.</p>
<p>I think the part I was getting tripped up over is that it seems like the btree is returned from a genserver to the caller. And it looked to me like the btree contains the root, which in return has a list of references to children. I thought all of these would have to be deep copied to the caller from the genserver.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="314263" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/question-about-memory-copy/60905/14">Post #13</a>
	                </div>
	            </div>
              <div id="likers-container-314263" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="314263"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #13"></div>
  </section>
</div>
    <div class="postbit" id="314291" data-post-id="314291">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="lucaong" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/lucaong/120/21794_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  lucaong
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<blockquote>
<p>And it looked to me like the btree contains the root, which in return has a list of references to children. I thought all of these would have to be deep copied to the caller from the genserver.</p>
</blockquote>
<p>Good point. The reason why the subtree referenced by the root does not get copied to the GenServer caller is that those references are not standard memory references, but rather pointers to an offset in the database file. <code>CubDB</code> knows how to follow such pointers on demand to access the file in the correct locations when reading and traversing the tree.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="314291" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/question-about-memory-copy/60905/15">Post #14</a>
	                </div>
	            </div>
              <div id="likers-container-314291" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="314291"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-last-post cat-last-post" title="Last post!"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <span class="all-loaded">— All posts loaded —</span>
</div></template></turbo-stream>