> 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]