> On Apr 25, 2017, at 6:18 PM, Jonathan Schleifer <[email protected]> 
> wrote:
> 
> Am 26.04.2017 um 01:11 schrieb Charles Srstka <[email protected]>:
> 
>> From the linked post:
>> 
>>> The performance penality is also much overblown, as people usually assume 
>>> that it is using a full blown mutex - which it is not. Unfortunately, the 
>>> situation is so bad that even GCC got it wrong (reported by me here).
>> 
>> Have to disagree with this statement. I have, more than once, spent some 
>> time tracking down severe performance issues in Pacifist, only to have it 
>> turn out that the problem was caused by an atomic property being accessed in 
>> a loop.
> 
> Can you give an example here? I'd really like to see this.

Unfortunately, I don’t remember the specifics anymore. This happened when I was 
converting Pacifist from MRC (Medieval Reference Counting ;-) ) to the newer 
Objective-C 2.0 with the @property syntax and ARC, which was years ago 
(nowadays, I’m converting it to Swift). I do think it had something to do with 
my model objects representing a file or folder inside a package; when opening 
the OS X installers, there end up being a *lot* of these, and some operations—I 
don’t remember exactly what—went from “Hmm, this is taking a little while” to 
“Hang on, let me go make a cup of coffee” after the conversion. I can’t 
remember if this was due to the spinlock, the autorelease pool getting slammed, 
or both, but going back and making all the @properties nonatomic solved it.

> Also, that still does not change the fact that nonatomic is even unsafe in 
> single-threaded code. Just writing the getter yourself as return [[foo 
> retain] autorelease] already gets rid of the spinlock, while not having the 
> unsafe side-effects of nonatomic.

I don’t really understand that concern when using Objective-C ARC or Swift. I 
read the bit in your post about valueForKey:, but that appears to behave 
properly for me. For the code below:

> #import <Foundation/Foundation.h>
> 
> @interface Foo: NSObject
> @end
> 
> @implementation Foo
> @end
> 
> @interface Bar: NSObject
> 
> @property (nonatomic, strong) Foo *foo;
> 
> @end
> 
> @implementation Bar
> 
> - (instancetype)init {
>       self = [super init];
>       
>       if (self == nil) { return nil; }
>       
>       self->_foo = [Foo new];
>       
>       return self;
> }
> 
> @end
> 
> void Baz(Bar *bar) {
>       Foo *foo = [bar valueForKey:@"foo"];
>       
>       NSLog(@"foo is %@", foo);
> }
> 
> int main(int argc, char *argv[]) {
>       @autoreleasepool {
>               Baz([Bar new]);
>       }
> }

the disassembly for Baz(), compiled with -Os and -fobjc-arc, looks like this:

> 0000000100000e25      pushq   %rbp
> 0000000100000e26      movq    %rsp, %rbp
> 0000000100000e29      pushq   %rbx
> 0000000100000e2a      pushq   %rax
> 0000000100000e2b      movq    0x456(%rip), %rsi ## Objc selector ref: 
> valueForKey:
> 0000000100000e32      leaq    0x21f(%rip), %rdx ## Objc cfstring ref: @"foo"
> 0000000100000e39      callq   *0x1d1(%rip) ## Objc message: -[%rdi 
> valueForKey:]
> 0000000100000e3f      movq    %rax, %rdi
> 0000000100000e42      callq   0x100000ec8 ## symbol stub for: 
> _objc_retainAutoreleasedReturnValue
> 0000000100000e47      movq    %rax, %rbx
> 0000000100000e4a      leaq    0x227(%rip), %rdi ## Objc cfstring ref: @"foo 
> is %@"
> 0000000100000e51      xorl    %eax, %eax
> 0000000100000e53      movq    %rbx, %rsi
> 0000000100000e56      callq   0x100000eb0 ## symbol stub for: _NSLog
> 0000000100000e5b      movq    %rbx, %rdi
> 0000000100000e5e      addq    $0x8, %rsp
> 0000000100000e62      popq    %rbx
> 0000000100000e63      popq    %rbp
> 0000000100000e64      jmpq    *0x1ae(%rip) ## literal pool symbol address: 
> _objc_release

As you can see, objc_retainAutoreleasedReturnValue is called as soon as we 
receive the result of valueForKey:, and is not released until Baz() exits, thus 
ensuring that ‘foo' will remain valid until we are done with it. To my mind, in 
an ARC world, autorelease is nothing but an unneeded performance hit which only 
gains relevance if there is a chance that legacy MRC code might try to access 
the property, and in a typical modern project, the only MRC code I can imagine 
being involved would be in the Cocoa frameworks themselves. And if framework 
code is grabbing a value from code from God knows where that might do God knows 
what, not copying or retaining the value, and then, before it’s done, calling a 
callback that might change the unretained value that it grabbed—well, I’d argue 
that’s a bug in the framework.

Charles

 _______________________________________________
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