4 ms·
> Presumably my code has been less than optimally efficient or something Yep, it was either less efficient than it could be, or more clunky, or incorrect. I r
by nice_byte 4y ago
> Presumably my code has been less than optimally efficient or something
Yep, it was either less efficient than it could be, or more clunky, or incorrect.
I remember back when boost was still a thing, everyone using boost::shared_ptr indiscriminately. Refcounting has a very nontrivial cost to it if implemented correctly.
Things like rvalue refs and std::move allow to properly implement the concept of "ownership transfer", obviating the need for costly ref counting in the majority of cases.
- PaulDavisThe1st 4y agoI've been using boost::shared_ptr for 22+ years. My code has no concept of ownership transfer, ever. The reason for shared_ptr<T> in our codebase is not to move ownership around, but to ensure correct lifetimes. For examples, objects in the model cannot die until the view has dropped references to them.
- nice_byte 4y agoYup, that's bad. Unless you actually have a complicated ownership scheme or shared state across multiple threads, unique ownership is preferable on all accounts. At the point where 1) your object graph is complex enough to warrant the ubiquitous use of shared pointers; 2) you can afford the performance hit it's better to use an actual garbage collector, even if it's bolted-on unreal engine-style. With shared_ptr-style ref counting, every dtor is potentially a bomb waiting to go off causing a cascading effect. It's actually less predictable than a GC that you can run manually at fixed intervals or whenever a convenient opportunity arises.
- deadbeeves 4y ago>It's actually less predictable than a GC that you can run manually at fixed intervals or whenever a convenient opportunity arises. Not really. It's difficult to reason about, but it's entirely deterministic, unlike a tracing GC.
- nice_byte 4y agowhen you cross a certain level of complexity, the deterministic nature becomes a Turing tarpit of sorts: yes, it's "deterministic", but the number of factors affecting the behavior is so large and their interactions so complex that it might as well be "non-deterministic" -- it's impractical to reason about in detail.
- rowanG077 4y agoI disagree. The big point of the determinism is that you can actually trivially control when deallocation occurs. In fact even if you don't want to manually reason about there are tools which can graphically show you when objects are deallocated.
- fluoridation 4y agoI'll take the "almost non-deterministic" over the non-deterministic. Computers are very good at reasoning about complex deterministic systems.
- nice_byte 4y ago...and a garbage collector is one of those. It's not magic fairy dust, it's still software that works on the same processing unit as your program, and obeys the same rules. Computers are finite automata, they can't beget true randomness, so any software system that is isolated to a single machine is "deterministic", if you have enough context.
- PaulDavisThe1st 4y ago> Computers are finite automata, they can't beget true randomness Plenty of peripheral inputs that can be used to induce true randomness.
- nice_byte 4y ago...of which the computer is not the source.
- PaulDavisThe1st 4y agoOur object graph is for a DAW, one of the most complex applications floating around. Multiple threads, some with RT constraints, multiple UIs acting as both view and controller. No GC acceptable here.
- nice_byte 4y agoas long as you can control when GC runs, it can be acceptable for applications with soft-realtime constraints (not all GC languages give you that level of flexibility though). at least I would prefer that situation over being faced with cascading destruction of refcounted objective-c objects at the most inconvenient moment, with no other recourse than complete rearchitecting.
- PaulDavisThe1st 4y agothe GC doesn't solve the problem of no-use-after-destruction, only the timing (and potentially thread) of destructor calling. you still need a refcnt'ing mechanism to make sure that nothing can be considered for GC before nobody is holding a reference to it anymore.
- gumby 4y ago> to ensure correct lifetimes Refcounted pointers don't make that guarantee. They just guarantee that if they are incorrect they will not deallocate (== will leave garbage) and thus never result in a use-after-deletion. Most of the time they are fine but they can't handle circular structures. This is why C++ has the weak_ptr.
- PaulDavisThe1st 4y agoNo use-after-deletion is precisely what is required. And yes, we use weak_ptr too, for some things. The alternative is "no language-level references, any time you want object "Foo", go look it up in some table". We opted not to do that.