7 ms·
If you're living without a garbage collector, avoiding that pointer return is potentially quite a big deal. "Just use a GC" is a viable answer to this in many
by dasmoth 13y ago
If you're living without a garbage collector, avoiding that pointer return is potentially quite a big deal.
"Just use a GC" is a viable answer to this in many circumstances, but probably not all.
- pkolaczk 13y ago"Just use a GC" is not a viable answer in the C++ world, because for C++, contrary to Java, there are no GCs of acceptable throughput and pause times.
- Ono-Sendai 13y agoYou can use automatic reference counting.
- pkolaczk 13y agoIt is sometimes handy, but generally compared to GC it is slow and incurs lots of contention in multithreaded programs. Imagine you return a reference-counted pointer from a function. Then every call to this function is a lock/unlock and CPU cache synchronization. And if the pointed object is shared between threads (even for read-only access) this might lead to lot of contended locks/unlocks, which is extremely costly.
- detrino 13y agoThe synchronization you mention is really rare, it only happens when you make a copy (not a move!) of a std::shared_ptr. If you have a std::shared_ptr<X>, then most of the time you will be passing around "X &" or "std::shared_ptr<X> &" and no copies will happen. Do you have an example of why a function would be returning a std::shared_ptr<X> by value that wasn't a move?
- pkolaczk 13y agoTo return a shared_ptr you first had to create it. So even if it optimizes the move, it doesn't optimize away the creation of the pointer and its destruction. As of using naked references, you're right, but if you can use naked references, why ever use shared_ptr? Naked references are fine when you know the lifetime of the object. Don't get me wrong - shared pointers are useful in many scenarios, but they are not a general replacement for GC.
- pkolaczk 13y agoBTW: Here is the post of someone who thought he can use shared_ptr as a poor-man's GC: http://stackoverflow.com/questions/2502394/the-cost-of-passing-by-shared-ptr http://stackoverflow.com/questions/2502394/the-cost-of-passi... shared_ptr took 17% of time. This is far beyond what GC takes even in a very memory heavy Java application (typically GC stays below 1% overhead). I'm not saying you shouldn't use shared_ptr at all, but only: be careful.
- detrino 13y agoNovices also sometimes erroneously pass std::vector by value, that doesn't mean std::vector is slow. Maybe you did not read the entire post before linking it. The conclusion was he changed his code to pass by reference and 17.77% became .27%.
- eliasmacpherson 13y agoThanks for pointing that out, I had heard horror stories before and was willing to take 17.77% at face value!
- detrino 13y agoYou can use naked references because most functions aren't acquiring ownership of a shared_ptr.
- bitkrieg 13y agoI always hear about how use of mutexes is costly but i never actually encountered a significant performance hit from using synchronization. Unless, of course, you have like 10 threads frequently accessing the same memory, which is more a design issue.
- pkolaczk 13y agoUncontended interlocked operation is typically about 100-300 CPU cycles. Uncontended mutex is about 30x-50x that. If there is contention, multiply everything by another 100x. Additionally these instructions impact not only the calling thread but also other threads by forcing cache synchronization. Therefore a relatively simple operation like pointer assignment can be one cycle when using GC and a hundred to several thousands cycles when using refcounting. Sometimes you can ignore this overhead, sometimes not - depends on how often you do that. http://software.intel.com/en-us/articles/choosing-between-synchronization-primitives http://software.intel.com/en-us/articles/choosing-between-sy...
- Ono-Sendai 13y agoOn what CPU? on my i7s it's much faster. on the order of 50 cycles for a uncontended mutex lock and release i think. I can dig out the values if anyone cares.
- eliasmacpherson 13y agohttps://en.wikipedia.org/wiki/Boehm_garbage_collector https://en.wikipedia.org/wiki/Boehm_garbage_collector They use this in Mono, what do you mean by throughput and pause times? Is it far inferior to the Java GC?
- Skinney 13y agoThey stopped using Boehm since 3.2 release of Mono. In certain cases the new GC is 10x faster.
- pkolaczk 13y agoIt is. Actually it is in a completely different league: 1. non-generational (= low throughput) 2. imprecise (= no guarantees on freeing unreferenced memory) 3. stop-the-world (= long pauses) 4. non-compacting (= allocation is slow and fragmentation still might be a problem)