<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Wed, Oct 19, 2016 at 6:24 PM, Benjamin Kramer via llvm-dev <span dir="ltr"><<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">In terms of performance shared_ptr has a number of disadvantages. One<br>
is that it always uses atomics even though most IntrusiveRefCntPtrs<br>
are used in single-threaded contexts. Another is weak_ptr adding a lot<br>
of complexity to the implementation, IntrusiveRefCntPtr doesn't<br>
support weak references.<br>
<br>
With that it's hard to make a case for changing uses of<br>
IntrusiveRefCntPtr as it's a non-trivial amount of work<br>
(IntrusiveRefCntPtr binds the reference count to the object itself,<br>
shared_ptr doesn't. Figuring out when a value held by an<br>
IntrusiveRefCntPtr is passed around by raw pointer and stuffed into<br>
another IntrusiveRefCntPtr is hard) with potential negative<br>
performance impact.<br>
<div class="gmail-HOEnZb"><div class="gmail-h5"><span style="color:rgb(34,34,34)"></span></div></div></blockquote><div> </div><div>In terms of performance, the whole concept has a number of disavantages :-)</div><div><br></div><div>I recently tried an experiment. I compiled a 40000 line C file (concatenated all the files of a project together) to .bc with clang, and then ran llc on it. I tried it on both Ubuntu 16.04 x64 and on an Odroid XU-4 ARM board. with very similar results.</div><div><br></div><div>I made a tiny library with a 1 GB static char array. I made a malloc() that simply bumped a pointer (prepending a 32 bit object size, just for realloc(), grrrrrr kill it with fire), and a free() that is an empty function. There's a calloc() that calls the above malloc() and then memset(). And a realloc() that is a no-op if the size is smaller, or does malloc(), memcpy() if bigger.</div><div><br></div><div>Then I used LD_PRELOAD to replace the standard malloc library with mine.</div><div><br></div><div>Result: ~10% faster execution than llc without LD_PRELOAD, and ~180 MB of the array used (120 MB on the 32 bit ARM).</div><div><br></div><div>Then I built BDW GC as a malloc replacement (with free() as a no-op) and used LD_PRELOAD with it.</div><div><br></div><div>Result: ~20% faster execution than llc without LD_PRELOAD, and ~10 MB of RAM used.</div><div><br></div><div>In this experiment all the reference counting in IntrusiveRefCntPtr or shared_ptr or whatever still takes place, the same as before. But at the end, when it decides to call free, it's a no-op. So all the reference-counting machinery is a complete waste of time and code and RAM and the program would run strictly faster if it was ripped out.</div><div><br></div><div>I don't know for sure (it's a lot more work to try!), but I would not be surprised to see a further 10%-20% speedup.</div><div><br></div><div><br></div><div>And then you come to the cognitive load on the programmer, trying to decide whether to use IntrusiveRefCntPtr or shared_ptr or unique_ptr or auto_ptr or weak_ptr or whether and where to call free()/delete. And the extra typing needed to write it instead of using a raw pointer. And the extra time and cognitive load to read the code. And for what? </div><div><br></div></div></div></div>