<div dir="ltr">Hi Peter, thanks for taking a look.<div><br></div><div>I would expect the compiler should generate a read only static string with the name of the function whenever the #function directive is used. I would expect that should not cause a leak.</div><div><br></div><div>If I modify the onSet function to replace a static string as the default value instead of using #function, there is no leak, so this seems like a bug to me.</div><div><br></div><div>Anyone have other ideas or opinions on this?</div><div><br></div><div>Thanks, Ed</div><div><br></div><div>--------------------------------------------------------</div><div><div>import Foundation</div><div><br></div><div>class A {</div><div><span style="white-space:pre">        </span>var counter = 0 {</div><div>//<span style="white-space:pre">                </span>didSet { onSet(&quot;counter&quot;) }  // no leak</div><div><span style="white-space:pre">                </span>didSet { onSet() }  // huge leak</div><div><span style="white-space:pre">        </span>}</div><div><br></div><div><span style="white-space:pre">        </span>var properties = [&quot;counter&quot; : 0]</div><div>//<span style="white-space:pre">        </span>func onSet(_ name: String = #function) { // leaks</div><div>//<span style="white-space:pre">                </span>properties[name]! += 1</div><div>//<span style="white-space:pre">        </span>}</div><div><span style="white-space:pre">        </span>func onSet(_ name: String = &quot;counter&quot;) {  // no leak</div><div><span style="white-space:pre">                </span>properties[name]! += 1</div><div><span style="white-space:pre">        </span>}</div><div>}</div><div><br></div><div>var myclass = A()</div><div><br></div><div>for i in 0..&lt;10000000 {</div><div><span style="white-space:pre">        </span>myclass.counter = i</div><div>}</div><div><br></div><div>print(myclass.properties[&quot;counter&quot;]!)</div></div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Sun, Aug 27, 2017 at 6:59 PM, Peter Nicholls <span dir="ltr">&lt;<a href="mailto:swiftuser@peternicholls.co.uk" target="_blank">swiftuser@peternicholls.co.uk</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">I looked in to the memory alloc and every time the “leak” iterates it’s creating an string item on the auto release stack with “counter” - a few million of them, compared to just 1 string on the non- leak. It is also quite a lot slower than the non leak version.<br>
<br>
I looked at the compiled assembly intermediate and at allocation the only difference is that the non-leak allocates via a register and is just a byte, but the leak uses a memory pointer is a word and is _unnammed_.<br>
<br>
My thought is that this isn’t a bug at all, it’s how the compiler deals with an unnamed #function and thus infers _name.<br>
<br>
As i trawled through the assembly seemed to me the non leak is making efficient use of the registers, through the named #function / _name, where as the leak version is using actual memory (hence why it is so much slower) with a view to destroying the autocomplete stack (of 9million odd auto release objects at 8bytes at a time) when completed. You can see how the memory stacks!<br>
<br>
Now. As to why and IF Swift is INTENDED to do this, or if indeed you’re doing something unintended too.... I cannot say.<br>
<br>
If any of the above is incorrect, please chime in.<br>
<br>
Peter Nicholls<br>
First time post.<br>
<div><div class="h5"><br>
&gt; On 27 Aug 2017, at 18:56, Edward Connell via swift-users &lt;<a href="mailto:swift-users@swift.org">swift-users@swift.org</a>&gt; wrote:<br>
&gt;<br>
&gt; I reported this about a year ago, but it has never been fixed and it seems like it should be fixed for the Swift 4.0 release.<br>
&gt;<br>
&gt; Here is a simple repro case. If you watch the memory monitor as it runs, you see memory consumption climb to 2.7GB when using #function, and no memory increase when using a static string.<br>
&gt;<br>
&gt; import Foundation<br>
&gt;<br>
&gt; class A {<br>
&gt;       var counter = 0 {<br>
&gt; //            didSet { onSet(&quot;counter&quot;) }  // no leak<br>
&gt;               didSet { onSet() }  // huge leak<br>
&gt;       }<br>
&gt;<br>
&gt;       var properties = [&quot;counter&quot; : 0]<br>
&gt;       func onSet(_ name: String = #function) {<br>
&gt;               properties[name]! += 1<br>
&gt;       }<br>
&gt; }<br>
&gt;<br>
&gt; var myclass = A()<br>
&gt;<br>
&gt; for i in 0..&lt;10000000 {<br>
&gt;       myclass.counter = i<br>
&gt; }<br>
&gt;<br>
&gt; print(myclass.properties[&quot;<wbr>counter&quot;]!)<br>
&gt;<br>
</div></div>&gt; ______________________________<wbr>_________________<br>
&gt; swift-users mailing list<br>
&gt; <a href="mailto:swift-users@swift.org">swift-users@swift.org</a><br>
&gt; <a href="https://lists.swift.org/mailman/listinfo/swift-users" rel="noreferrer" target="_blank">https://lists.swift.org/<wbr>mailman/listinfo/swift-users</a><br>
<br>
</blockquote></div><br></div>