<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("counter") } // 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 = ["counter" : 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 = "counter") { // 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..<10000000 {</div><div><span style="white-space:pre">        </span>myclass.counter = i</div><div>}</div><div><br></div><div>print(myclass.properties["counter"]!)</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"><<a href="mailto:swiftuser@peternicholls.co.uk" target="_blank">swiftuser@peternicholls.co.uk</a>></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>
> On 27 Aug 2017, at 18:56, Edward Connell via swift-users <<a href="mailto:swift-users@swift.org">swift-users@swift.org</a>> wrote:<br>
><br>
> 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>
><br>
> 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>
><br>
> import Foundation<br>
><br>
> class A {<br>
> var counter = 0 {<br>
> // didSet { onSet("counter") } // no leak<br>
> didSet { onSet() } // huge leak<br>
> }<br>
><br>
> var properties = ["counter" : 0]<br>
> func onSet(_ name: String = #function) {<br>
> properties[name]! += 1<br>
> }<br>
> }<br>
><br>
> var myclass = A()<br>
><br>
> for i in 0..<10000000 {<br>
> myclass.counter = i<br>
> }<br>
><br>
> print(myclass.properties["<wbr>counter"]!)<br>
><br>
</div></div>> ______________________________<wbr>_________________<br>
> swift-users mailing list<br>
> <a href="mailto:swift-users@swift.org">swift-users@swift.org</a><br>
> <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>