> +1. Different projects have different types of code, and I think a lot of the 
> “don’t worry about micro-optimizations, _____ doesn’t really affect your 
> performance” statements apply to high-level code like in a typical app, but 
> do not apply to lower-level code that’s doing heavy lifting. In my case, I 
> work on a document-oriented database engine that has some very 
> performance-critical code in it, and overhead like atomic properties is very 
> noticeable in Instruments in some areas.

There are always exceptions when you have some performance critical hot path - 
but that doesn't mean the optimizations for the hot path now need to be applied 
to everything where it can in some way or another be applied.

Also, why would you even use a property if you care that much about 
performance? Access the ivar instead, that saves you the entire dispatch!

> It’s not clear how much overhead there is in locating that spinlock, though. 
> It’s accessed as "PropertyLocks[slot]”, where PropertyLocks is a global C++ 
> object of class StripedMap. I haven’t looked up the implementation of 
> StripedMap, but this is a global table with an entry for every atomic 
> property of every object in memory. And that table needs to be thread-safe, 
> so it either has its own locks, or it has a complex lockless algorithm that 
> relies on atomic instructions (which are themselves expensive as they 
> invalidate CPU caches.)

I think it boils down to hashing the property and locking the spinlock in a 
certain slot depending on the hash. Sure, this *will* have collisions, but 
since no deadlocking is possible and the time required to set / get a property 
is short, this is fine. So no, no extra locking for the property locks itself 
and no atomics for that (except for the spinlock itself).

>> The cost of atomic is roughly that of a single retain. 
> 
> Nope, it’s a retain plus an autorelease, plus the work of doing the deferred 
> release while draining the autorelease table. (Retain and release also 
> involve accessing global tables indexed by object. IIRC these are lockless; 
> Mike Ash has delved into the implementation on his blog.)

Well, they work similar to the property locks. But I agree that the case of 
atomic is actually that of two retains and an autorelease - the cost of the 
retain that I meant was only that of the spinlock. I'll correct this.

> objc_retain and objc_release are other very hot functions in typical 
> Instruments profiles I look at. To the point that I’ve started using 
> _unsafe_unretained in method/function implementation signatures to prevent 
> parameters from getting retained/released unnecessarily (I’ve got a macro 
> “UU” for it.) Yes, I see real-world gains for this when I use it in very hot 
> functions.

I can see how this is useful in some situation, just like IMP caching and 
directly accessing ivars is. However, this should remain a special case that is 
only used in extreme situations and not just used everywhere because there's 
nothing actively preventing you from doing so.

> Your point [Jonathan] about releasing dangling references is valid, Jonathan; 
> but in practice I run into this problem very rarely, and I’ve been using 
> nonatomic properties (and getters that simply “return _obj” without the 
> retain/autorelease dance) since 2000. For me the tradeoff is worth it. For 
> people writing typical app code, maybe not. But I think the description in 
> your blog post is a bit one-sided.

True, there are special cases. Let me add something that makes clear that I 
don't say "Never use nonatomic", but that I say "Don't just add nonatomic 
everywhere just because without thinking if it actually makes sense".

--
Jonathan

 _______________________________________________
Do not post admin requests to the list. They will be ignored.
Objc-language mailing list      ([email protected])
Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/objc-language/archive%40mail-archive.com

This email sent to [email protected]

Reply via email to