<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Jan 22, 2016, at 11:22 AM, Daniel Tartaglia via swift-users <<a href="mailto:swift-users@swift.org" class="">swift-users@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">If I have a large struct with lots of sub-structs and I assign to just one field of one of the sub-structs, will the system make a deep copy of the struct or a shallow copy where the unmodified portions of the object still point the same memory as the original struct?</div><div class=""><br class=""></div><div class="">In other words, given this code:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; line-height: normal; font-family: Menlo;" class=""><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">struct</span> SubStruct {</div><div style="margin: 0px; line-height: normal;" class=""> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">var</span> a: <span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Int</span> = <span style="font-variant-ligatures: no-common-ligatures; color: #272ad8" class="">0</span></div><div style="margin: 0px; line-height: normal;" class=""> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">var</span> b: <span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Int</span> = <span style="font-variant-ligatures: no-common-ligatures; color: #272ad8" class="">0</span></div><div style="margin: 0px; line-height: normal;" class="">}</div><div style="margin: 0px; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">struct</span> VeryLarge {</div><div style="margin: 0px; line-height: normal;" class=""> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">var</span> subStructA = <span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">SubStruct</span>()</div><div style="margin: 0px; line-height: normal;" class=""> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">var</span> subStructB = <span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">SubStruct</span>()</div><div style="margin: 0px; line-height: normal;" class=""> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">var</span> subStructC = <span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">SubStruct</span>()</div><div style="margin: 0px; line-height: normal; color: rgb(0, 132, 0);" class=""><span style="" class=""> </span>// lots of other stuff</div><div style="margin: 0px; line-height: normal;" class="">}</div><div style="margin: 0px; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; line-height: normal; color: rgb(79, 129, 135);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">func</span><span style="" class=""> bar(</span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">var</span><span style="" class=""> vl: </span>VeryLarge<span style="" class="">) -> </span>VeryLarge<span style="" class=""> {</span></div><div style="margin: 0px; line-height: normal;" class=""> vl.<span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">subStructA</span>.<span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">a</span> = <span style="font-variant-ligatures: no-common-ligatures; color: #272ad8" class="">5</span></div><div style="margin: 0px; line-height: normal;" class=""> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">return</span> vl</div><div style="margin: 0px; line-height: normal;" class="">}</div><div style="margin: 0px; line-height: normal; min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">let</span> vl1 = <span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">VeryLarge</span>()</div><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">let</span> vl2 = <span style="font-variant-ligatures: no-common-ligatures; color: #31595d" class="">bar</span>(<span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">vl1</span>)</div><div class=""><br class=""></div></div></div><div style="margin: 0px; line-height: normal; font-family: Menlo; min-height: 14px;" class="">Will vl2.subStructB be a copy of vl1.subStructB, or an entirely new object?</div><div class=""><br class=""></div><div class="">I’m worried about performance when making small changes to large objects.</div></div></div></blockquote><br class=""></div><div>Semantically, vl2 is always a distinct value, though how that ends up manifesting depends on the optimizer. By default, struct fields are stored in-line, like C structs, so sizeof(VeryLarge) will be sizeof(SubStruct) * 3 + sizeof(lots of other stuff), and a copy will be a full copy. If you want copy-on-write behavior, you currently have to implement it yourself, or build from already-implemented COW value types like Array. When structs pass a certain size threshold, the calling convention changes over to passing and returning them indirectly, though 'bar' will still naively introduce a copy to transfer the modified value from the argument to the result buffer. However, in optimized builds, if bar is inlined, then I'd expect this to ultimately reduce down to an in-place modification without copies, since vl1 is never used after assigning vl2.</div><br class=""><div class="">-Joe</div></body></html>