Re: Spinning the busy indicator

2015-04-30 Thread Quincey Morris
On Apr 30, 2015, at 23:41 , Graham Cox  wrote:
> 
> But if I leave it at the default, the same blocking problem is apparent. 
> Logging the default QoS, I see it’s -1, which equates to 
> NSQualityOfServiceDefault. Setting it to 
> NSOperationQualityOfServiceBackground things are fine. Therefore at the very 
> least the documentation is incorrect.

Look here:

https://developer.apple.com/library/mac/releasenotes/Foundation/RN-Foundation/#10_10QoS
 


It depends on the NSOperationQueue and the underlying dispatch queue. (Keep in 
mind that these are beta release notes. I don’t know that there were ever any 
final release notes for 10.10.)



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Spinning the busy indicator

2015-04-30 Thread Graham Cox

> On 1 May 2015, at 3:53 pm, Graham Cox  wrote:
> 
> It looks as if to be sure I’m going to have to drop down a level and create 
> my own NSOperations.

Well that’s an interesting result - creating my own NSOperation with a QoS of 
NSOperationQualityOfServiceBackground and adding it to my queue produces a 
perfectly smooth and non-blocking app. If I use -addOperationWithBlock: things 
are screwed up.

For [NSOperation qualityOfService] Apple says:

> The default value of this property is NSOperationQualityOfServiceBackground 
> and you should leave that value in place whenever possible.

But if I leave it at the default, the same blocking problem is apparent. 
Logging the default QoS, I see it’s -1, which equates to 
NSQualityOfServiceDefault. Setting it to NSOperationQualityOfServiceBackground 
things are fine. Therefore at the very least the documentation is incorrect. I 
do wonder if this isn’t actually a bug though - if something somewhere is 
interpreting -1 to mean a very high priority instead of a low one, that’s going 
to screw things up pretty badly all over the place.

I’d be interested to know if this has changed from 10.9 or earlier (I’m on 
10.10).


—Graham



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Spinning the busy indicator

2015-04-30 Thread dangerwillrobinsondanger
In addition to GCD which is a good idea, you might look into the Accelerate 
framework to see if it offers something.  There's a fairly recent WWDC video 
about it. 

Sent from my iPhone

> On 2015/05/01, at 14:53, Graham Cox  wrote:
> 
> 
>> On 1 May 2015, at 3:28 pm, Quincey Morris 
>>  wrote:
>> 
>> ― I don’t see anything really wrong at any point, other than it looks 
>> unresponsive because it’s very busy for a while.
> 
> Well, thanks for having a look and taking an interest - and apologies for the 
> rather scrappy coding.
> 
>> 
>> I would suggest you use QoS to lower the priority of your calculations. This 
>> will let UI updates and other important main thread stuff go through ahead 
>> of the calculations. The calculations should probably be at the lowest or 
>> second-lowest QoS level.
> 
> 
> I must admit I hadn’t given any thought to the QoS - just learning my way 
> around this stuff.
> 
> So, the docs say (ha! here we go again…) that the default QoS is 
> NSOperationQualityOfServiceBackground. This appears to be the LOWEST QoS 
> constant. However, it also states that it is only used if the NSOperation 
> itself doesn’t set this value, but because addOperationWithBlock: creates its 
> own NSOperation internally (that we mere mortals don’t get to access), it 
> might be assigning a value that overrides this. Unhelpfully, the simple CPU 
> usage view in XCode only states "QoS unavailable”.
> 
> It looks as if to be sure I’m going to have to drop down a level and create 
> my own NSOperations.
> 
> 
>> Lowering the QoS might take care of your problem, but if it doesn’t, you’re 
>> faced with some decisions about “number of threads to use”. If it comes to 
>> this, I wonder if it’s a mistake in this case to let the processing fall 
>> through to GCD like you’re doing. You have so much processing to do, it’s 
>> going to impact the system badly if you tell the system to get it done as 
>> fast as possible. This *may* be a case where you create your own pool of 
>> NSThreads (either the number of logical CPUs or one less than that), and 
>> parcel the work out to them, so that it can’t get out of hand. (However, you 
>> might still use NSOperationQueue to manage things for you, but instead of an 
>> individual NSOperation doing the work, it would give the work to a NSThread 
>> in your pool.)
> 
> I reckon if it comes to that there’s probably going to be very little value 
> left in NSOperationQueue so I may as well just use the GCD API directly. But 
> I’ll experiment a bit more…
> 
> 
> ―Graham
> 
> 
> 
> ___
> 
> Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
> 
> Please do not post admin requests or moderator comments to the list.
> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
> 
> Help/Unsubscribe/Update your Subscription:
> https://lists.apple.com/mailman/options/cocoa-dev/dangerwillrobinsondanger%40gmail.com
> 
> This email sent to dangerwillrobinsondan...@gmail.com

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Spinning the busy indicator

2015-04-30 Thread Quincey Morris
On Apr 30, 2015, at 22:53 , Graham Cox  wrote:
> 
> It looks as if to be sure I’m going to have to drop down a level and create 
> my own NSOperations.

You can create your own (non-serial) GCD queue with any desired QoS, then set 
your NSOperationQueue to use it.


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Spinning the busy indicator

2015-04-30 Thread Graham Cox

> On 1 May 2015, at 3:28 pm, Quincey Morris 
>  wrote:
> 
> — I don’t see anything really wrong at any point, other than it looks 
> unresponsive because it’s very busy for a while.

Well, thanks for having a look and taking an interest - and apologies for the 
rather scrappy coding.

> 
> I would suggest you use QoS to lower the priority of your calculations. This 
> will let UI updates and other important main thread stuff go through ahead of 
> the calculations. The calculations should probably be at the lowest or 
> second-lowest QoS level.


I must admit I hadn’t given any thought to the QoS - just learning my way 
around this stuff.

So, the docs say (ha! here we go again…) that the default QoS is 
NSOperationQualityOfServiceBackground. This appears to be the LOWEST QoS 
constant. However, it also states that it is only used if the NSOperation 
itself doesn’t set this value, but because addOperationWithBlock: creates its 
own NSOperation internally (that we mere mortals don’t get to access), it might 
be assigning a value that overrides this. Unhelpfully, the simple CPU usage 
view in XCode only states "QoS unavailable”.

It looks as if to be sure I’m going to have to drop down a level and create my 
own NSOperations.


> Lowering the QoS might take care of your problem, but if it doesn’t, you’re 
> faced with some decisions about “number of threads to use”. If it comes to 
> this, I wonder if it’s a mistake in this case to let the processing fall 
> through to GCD like you’re doing. You have so much processing to do, it’s 
> going to impact the system badly if you tell the system to get it done as 
> fast as possible. This *may* be a case where you create your own pool of 
> NSThreads (either the number of logical CPUs or one less than that), and 
> parcel the work out to them, so that it can’t get out of hand. (However, you 
> might still use NSOperationQueue to manage things for you, but instead of an 
> individual NSOperation doing the work, it would give the work to a NSThread 
> in your pool.)

I reckon if it comes to that there’s probably going to be very little value 
left in NSOperationQueue so I may as well just use the GCD API directly. But 
I’ll experiment a bit more…


—Graham



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Spinning the busy indicator

2015-04-30 Thread Quincey Morris
On Apr 30, 2015, at 21:46 , Graham Cox  wrote:
> 
> If anyone’s interested in having a look at what’s happening, I’ve put the 
> project sources up here: http://apptree.net/code/Gingerbread.zip 
> 
Here’s what I see:

— I took out your 3-thread limitation.

— I’m running on a 4-core i7, so there are 8 logical CPUs, and it uses 8 
threads for each “run”.

— I see the progress indicator appear, stop spinning for a while, spin for a 
while and disappear. It seems clear that it stops spinning simply because the 
CPUs are busy doing other things. I’m almost certain this is a red herring 
(though a UI issue, a point I’ll come back to).

— It takes several seconds to recalculate/redraw the view. Then it takes 
another few seconds for the CPUs to go idle. It looks like there’s a lot of 
catching up/cleaning up going on after its finished. Perhaps there’s a pile of 
delegate notifications pending? You really should look into this via 
Instruments.

— I don’t see anything really wrong at any point, other than it looks 
unresponsive because it’s very busy for a while.

I would suggest you use QoS to lower the priority of your calculations. This 
will let UI updates and other important main thread stuff go through ahead of 
the calculations. The calculations should probably be at the lowest or 
second-lowest QoS level.

Lowering the QoS might take care of your problem, but if it doesn’t, you’re 
faced with some decisions about “number of threads to use”. If it comes to 
this, I wonder if it’s a mistake in this case to let the processing fall 
through to GCD like you’re doing. You have so much processing to do, it’s going 
to impact the system badly if you tell the system to get it done as fast as 
possible. This *may* be a case where you create your own pool of NSThreads 
(either the number of logical CPUs or one less than that), and parcel the work 
out to them, so that it can’t get out of hand. (However, you might still use 
NSOperationQueue to manage things for you, but instead of an individual 
NSOperation doing the work, it would give the work to a NSThread in your pool.)



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Spinning the busy indicator

2015-04-30 Thread Steve Mills
On May 1, 2015, at 00:08:33, Graham Cox  wrote:
> 
> Well, it’s always gratifying to find I’m not alone ;)
> 
> How did you figure out a value that leaves one for the main thread? The 
> actual value returned is -1 for 
> NSOperationQueueDefaultMaxConcurrentOperationCount, not the actual number it 
> calculated. I guess there’s a way to get the number of cores, but that isn’t 
> necessarily the whole story…?

I just dinked around until I found something that worked for my app (which can 
create many more ops than there are cores). I ended up with:

const NSUIntegernumCores = [[NSProcessInfo processInfo] 
processorCount] * 2 - 1;

[self.searchQueue setMaxConcurrentOperationCount:(NSInteger)numCores];

--
Steve Mills
Drummer, Mac geek


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Spinning the busy indicator

2015-04-30 Thread Graham Cox

> On 1 May 2015, at 3:02 pm, Steve Mills  wrote:
> 
> I’ve run into this too, where letting the OS figure out how many operations 
> to queue at once doesn’t always work like a human wants it to work. I ended 
> up doing what you did - leave one for the main thread. 
> NSOperationQueueDefaultMaxConcurrentOperationCount really isn’t smart enough, 
> or they need to add another constant 
> NSOperationQueueDefaultMaxConcurrentButDontBeAJerkOperationCount.
> 


Well, it’s always gratifying to find I’m not alone ;)

How did you figure out a value that leaves one for the main thread? The actual 
value returned is -1 for NSOperationQueueDefaultMaxConcurrentOperationCount, 
not the actual number it calculated. I guess there’s a way to get the number of 
cores, but that isn’t necessarily the whole story…?

—Graham



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Spinning the busy indicator

2015-04-30 Thread Steve Mills
On Apr 30, 2015, at 23:46:53, Graham Cox  wrote:
> 
> Well, here’s a huge clue.
> 
> I use NSOperationQueue with the default -maxConcurrentOperationCount which is 
> NSOperationQueueDefaultMaxConcurrentOperationCount, i.e. let the system 
> figure it out. That appears to create 4 threads for my particular machine, 
> which has a Core i3 (2 cores) CPU. My peak CPU usage is reported as 418%. I’m 
> not sure how it achieves that from a dual core CPU, but one would assume that 
> Apple know what they’re doing [/irony].
> 
> So, I tried setting that NSOperationQueue property directly to something 
> less, and lo-and-behold, the problem goes away with a limit of 3 or less. A 
> limit of 4 produces the same problem.
> 
> This appears to suggest that if you let NSOperationQueue take all of the CPU 
> resources, the main thread is left high and dry if it needs to create another 
> thread, e.g. for an XPC call. Maybe this is intentional, but it’s a bloody 
> nuisance - surely a better outcome for the “let the system figure it out” 
> would be to say “whatever the max is -1”, so it leaves some capacity in hand 
> for the main thread. The way it works now might give slightly better 
> performance overall, but it causes an app to hang unresponsively for some 
> indeterminate period in some cases. Of course I can set the limit to 3 
> myself, but if I found myself on a 16 core machine, that's very suboptimal.
> 
> I’m tempted to report this as a bug, but I’d like to hear what others think 
> about this first.

I’ve run into this too, where letting the OS figure out how many operations to 
queue at once doesn’t always work like a human wants it to work. I ended up 
doing what you did - leave one for the main thread. 
NSOperationQueueDefaultMaxConcurrentOperationCount really isn’t smart enough, 
or they need to add another constant 
NSOperationQueueDefaultMaxConcurrentButDontBeAJerkOperationCount.

--
Steve Mills
Drummer, Mac geek


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Spinning the busy indicator

2015-04-30 Thread Graham Cox

> On 1 May 2015, at 1:12 pm, Quincey Morris 
>  wrote:
> 
> Yes, they do say that. But as it happens I went to IB (6.3.1). The 
> “indeterminate” checkbox is right there, and if you uncheck it you get a 
> clock-style progress indicator. I guess the docs are out of date, though only 
> by about 4 or 5 major OS X versions. ;)


You’re right - there is another style of circular spinner you get with 
indeterminate = NO. Never noticed that before. And you’re right - the docs are 
out of date.

> I don’t have any answers here, just some random thoughts:
> 
> — Looking at your code, my intuition says that this smells like a reference 
> cycle problem, one that leads to queue blockage.
> 
> — Don’t use ‘performSelector…’ with ARC, since it typically can’t preserve 
> memory management correctness across that boundary. It’s uglier but 
> preferable to get back to the main thread via ‘dispatch_async 
> (dispatch_get_main_queue (), ^{ … });’. There’s an autocompletion snippet for 
> most of this.
> 
> — I’m not a big fan of NSOperationQueue. A simple GCD dispatch_async to the 
> default non-main queue seems more obvious to me. The only reason for using 
> NSOperationQueue is if you want a parallel operation count other than 1 (i.e. 
> serial) or “let the system decide” (i.e. the GCD default), provided that the 
> individual operations don’t block internally, which tends to mess GCD up. Or 
> if you want to be able to cancel operations, since there’s no API for that in 
> GCD itself. Or if you want selector-based operations rather than the 
> block-based ones you’re using.
> 
> — For anything to do with blocks running on background GCD threads, you need 
> to pay attention to the top level autorelease pool, and the place where 
> exceptions are caught. IIRC, in vanilla GCD, you have to provide these 
> yourself, but I don’t remember the NSOperation semantics.



Well, here’s a huge clue.

I use NSOperationQueue with the default -maxConcurrentOperationCount which is 
NSOperationQueueDefaultMaxConcurrentOperationCount, i.e. let the system figure 
it out. That appears to create 4 threads for my particular machine, which has a 
Core i3 (2 cores) CPU. My peak CPU usage is reported as 418%. I’m not sure how 
it achieves that from a dual core CPU, but one would assume that Apple know 
what they’re doing [/irony].

So, I tried setting that NSOperationQueue property directly to something less, 
and lo-and-behold, the problem goes away with a limit of 3 or less. A limit of 
4 produces the same problem.

This appears to suggest that if you let NSOperationQueue take all of the CPU 
resources, the main thread is left high and dry if it needs to create another 
thread, e.g. for an XPC call. Maybe this is intentional, but it’s a bloody 
nuisance - surely a better outcome for the “let the system figure it out” would 
be to say “whatever the max is -1”, so it leaves some capacity in hand for the 
main thread. The way it works now might give slightly better performance 
overall, but it causes an app to hang unresponsively for some indeterminate 
period in some cases. Of course I can set the limit to 3 myself, but if I found 
myself on a 16 core machine, that's very suboptimal.

> On 1 May 2015, at 2:20 pm, Roland King  wrote:
> 
> So I don’t think this has anything to do with your code at all, apart from 
> the fact your code makes the machine really busy. It seems the menu system 
> does a synchronous call out to an XPC service which doesn’t return in a 
> timely manner when the cpu is busy. This is all in the OS code (I’m on 
> Yosemite by the way). 
> 


I’m tempted to report this as a bug, but I’d like to hear what others think 
about this first.

If anyone’s interested in having a look at what’s happening, I’ve put the 
project sources up here: http://apptree.net/code/Gingerbread.zip As it’s only a 
toy/experimental project, there’s nothing in it that matters but it’s a bit 
rough and ready. Line 124 in GCMandelGenerator.m is where I manipulate the 
queue max count. Commenting that out gives the default behaviour, which shows 
the problem.


—Graham



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Spinning the busy indicator

2015-04-30 Thread Roland King
Doing a little bit of googling on some of the stuff in your stack trace, 
InstallEventHander and GlobalRegistryEventRegistered all seem to be part of 
HIToolBox. 

I just picked a random app of my own and stuck a few breakpoints in it to find 
every menu invocation in my app goes down pretty much the same path, including 
the synchronous xpc call following HIToolbox adding and removing event 
handlers, more than one actually. Every one. Just sticking logging on the 
synchronous xpc calls generates a lot of guff when you open a menu. 

All this seems to be calling out to some piece of LaunchServices with ‘addasn’ 
and ‘removeasn’ messages (looking up the stack you can see the strings put into 
the xpc dictionary). So the act of opening a menu appears to be registering for 
notifications from launchservices, I’m guessing so that it knows if the app 
ceases to be frontmost or similar. 

So I don’t think this has anything to do with your code at all, apart from the 
fact your code makes the machine really busy. It seems the menu system does a 
synchronous call out to an XPC service which doesn’t return in a timely manner 
when the cpu is busy. This is all in the OS code (I’m on Yosemite by the way). 

Noting the documented warning for using 
xpc_connection_send_message_with_reply_sync()

"If the response will be constructed with data that exists in-memory in the 
server, it is usually safe to make the API synchronous. But if constructing the 
response requires I/O, and it is likely to be called from the main thread (or a 
thread which synchronizes with the main thread), we highly encourage that you 
take the asynchronous route to avoid the risk of blocking the UI.”




> On 1 May 2015, at 10:59, Roland King  wrote:
> 
> 
> 
>> 
>> Stumped.
>> 
>> —Graham
>> 
> 
> I don’t have a lot more ideas than you, having been reading this thread (no 
> pun intended) for 2 days. 
> 
> Is this only happening when you click to bring up a menu when your app is 
> running or at other times too? I can’t currently think of a good reason why 
> opening a menu ends up resulting in an XPC call, worse, an XPC call which is 
> synchronous and waits for a reply, on the main thread. Do the classes/methods 
> in the trace, InstallEventHandler(), TEventTypeIndex, 
> GlobalRegistryEventRegistered and LSNotificationReceiver mean anything to 
> you, or anyone else? 
> 
> Might be time to grit teeth and break out Instruments. That can quite 
> usefully show you breakdowns by queue, by thread or by processor. Sometimes 
> just looking at the pattern gives you a clue what’s happening. It will surely 
> tell you if you have the CPUs all spun up to 100%. 
> 
> The xpc call which is hanging. Are xpc services always separate processes, I 
> thought so but someone can correct me if wrong. If so, it sounds like the xpc 
> service being used is starved of resources because the CPUs are busy 
> mandelbrotting, so it doesn’t reply very quickly and blocks your main thread. 
> If you open and close menus on a barebones system running just your app, can 
> you find another process which keeps spinning up? 
> 
> It looks to me that opening a menu calls some xpc service which is expected 
> to return quickly but doesn’t because the machine is swamped (Instruments 
> should be able to tell you if it is). Whether that xpc call is something the 
> OS does all the time or if there’s something in your app which is causing it, 
> can’t say. Synchronous calls to xpc services from the main thread would seem 
> to be something Apple is always telling devs not to do, so it’s probably 
> them. 
> 



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Spinning the busy indicator

2015-04-30 Thread Quincey Morris
On Apr 30, 2015, at 19:15 , Graham Cox  wrote:
> 
> Well, the docs say:
> 
>> This method only has an effect if style returns NSProgressIndicatorBarStyle. 
>> If style returns NSProgressIndicatorSpinningStyle, the indicator is always 
>> indeterminate, regardless of what you pass to this method.

Yes, they do say that. But as it happens I went to IB (6.3.1). The 
“indeterminate” checkbox is right there, and if you uncheck it you get a 
clock-style progress indicator. I guess the docs are out of date, though only 
by about 4 or 5 major OS X versions. ;)

> The code that schedules the work is:


I don’t have any answers here, just some random thoughts:

— Looking at your code, my intuition says that this smells like a reference 
cycle problem, one that leads to queue blockage.

— Don’t use ‘performSelector…’ with ARC, since it typically can’t preserve 
memory management correctness across that boundary. It’s uglier but preferable 
to get back to the main thread via ‘dispatch_async (dispatch_get_main_queue (), 
^{ … });’. There’s an autocompletion snippet for most of this.

— I’m not a big fan of NSOperationQueue. A simple GCD dispatch_async to the 
default non-main queue seems more obvious to me. The only reason for using 
NSOperationQueue is if you want a parallel operation count other than 1 (i.e. 
serial) or “let the system decide” (i.e. the GCD default), provided that the 
individual operations don’t block internally, which tends to mess GCD up. Or if 
you want to be able to cancel operations, since there’s no API for that in GCD 
itself. Or if you want selector-based operations rather than the block-based 
ones you’re using.

— For anything to do with blocks running on background GCD threads, you need to 
pay attention to the top level autorelease pool, and the place where exceptions 
are caught. IIRC, in vanilla GCD, you have to provide these yourself, but I 
don’t remember the NSOperation semantics.

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Spinning the busy indicator

2015-04-30 Thread Roland King


> 
> Stumped.
> 
> —Graham
> 

I don’t have a lot more ideas than you, having been reading this thread (no pun 
intended) for 2 days. 

Is this only happening when you click to bring up a menu when your app is 
running or at other times too? I can’t currently think of a good reason why 
opening a menu ends up resulting in an XPC call, worse, an XPC call which is 
synchronous and waits for a reply, on the main thread. Do the classes/methods 
in the trace, InstallEventHandler(), TEventTypeIndex, 
GlobalRegistryEventRegistered and LSNotificationReceiver mean anything to you, 
or anyone else? 

Might be time to grit teeth and break out Instruments. That can quite usefully 
show you breakdowns by queue, by thread or by processor. Sometimes just looking 
at the pattern gives you a clue what’s happening. It will surely tell you if 
you have the CPUs all spun up to 100%. 

The xpc call which is hanging. Are xpc services always separate processes, I 
thought so but someone can correct me if wrong. If so, it sounds like the xpc 
service being used is starved of resources because the CPUs are busy 
mandelbrotting, so it doesn’t reply very quickly and blocks your main thread. 
If you open and close menus on a barebones system running just your app, can 
you find another process which keeps spinning up? 

It looks to me that opening a menu calls some xpc service which is expected to 
return quickly but doesn’t because the machine is swamped (Instruments should 
be able to tell you if it is). Whether that xpc call is something the OS does 
all the time or if there’s something in your app which is causing it, can’t 
say. Synchronous calls to xpc services from the main thread would seem to be 
something Apple is always telling devs not to do, so it’s probably them. 


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Parent/child view controllers: when shall we use it?

2015-04-30 Thread Roland King

> On 1 May 2015, at 04:54, Colas B  wrote:
> 
> Dear cocoa-dev,
> When building a simple UIViewController, do I have to use 
> addChildViewController: if this VC "owns" other VCs?(By simple VC, I mean I 
> am not creating MyCustomNavigationController or something like that; just a 
> "plain old" VC)
> Imagine for example that I build a view controller (MyCustomVC) and its view 
> has a small subview (fbView) for a Facebook logo and a counter. This 
> "facebook view" is attached to a view controller (FacebookVC) that is called 
> when fbView is touched. So, the FacebookVC definitely needs to be a @property 
> of the MyCustomVC.In this situation, should I really use 
> addChildViewController: and all the mechanism to declare FacebookVC to be a 
> childController of MyCustomVC? 
> My belief is that: NO, in this situation it is not to be use. IMHO, 
> MyCustomVC is NOT a container view controller and the usage of child/parent 
> mechanism is only for UINavigationController, TabBar, ... or if I want to 
> create such a "general" class.
> So, am I wrong or am I right ?
> Thanks ;-)Colas 
> _

Had some difficulty completing understanding what you’re trying to do here but 
I think you’re not right in this instance. 

I’ll try putting it another way. If you have a view controller and its view 
contains subviews which are the views of a different view controller, then you 
must use the addChildViewController and other methods to make a correct 
hierarchy of view controllers. Any use of another view controller’s view in 
your view controller’s view requires that you set up (and tear down) the view 
controller parent child relationship. if you don’t, rotation won’t work, the 
view appearance/disappearance methods won’t work and various other methods 
passed down from view controller to view controller won’t work. 

So in your case it seems like your MyCustomVC’s view has, as subview, a fbView 
which is the ‘view’ of a FacebookVC. Before you add that view to your 
MyCustomVC’s view’s hierarchy you must make the FacebookVC a child of your 
MyCustomVC. 

TL;DR; If your VC’s view embeds a view from another VC, you must set up a 
parent-child relationship between the VCs
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Spinning the busy indicator

2015-04-30 Thread Graham Cox

> On 1 May 2015, at 10:18 am, Quincey Morris 
>  wrote:
> 
> On Apr 30, 2015, at 16:39 , Graham Cox  wrote:
>> 
>> As I mentioned it’s the spinning busy indicator, which is always 
>> indeterminate.
> 
> The circular style isn’t always indeterminate, though (I forgot) it looks 
> different when it’s not indeterminate.

Well, the docs say:

> This method only has an effect if style returns NSProgressIndicatorBarStyle. 
> If style returns NSProgressIndicatorSpinningStyle, the indicator is always 
> indeterminate, regardless of what you pass to this method.

However, I’m now fairly convinced that this is a red herring, and is a side 
effect of the more serious bug.

> 
> My app also hits a breakpoint at _dispatch_semaphore_wait_slow when I click 
> on a menu bar menu, also in the middle of talking to another process via XPC, 
> so I don’t think that’s a cause of your problem.
> 
> Instead, I suspect you have a memory management error that’s corrupting 
> something. Or a thread safety error that’s causing this as a side effect.


I’m starting to think that as well.

I’m using ARC - I keep trying to get on board with ARC, and every time I do I 
seem to run into this sort of difficult to track down issue. At this stage I’ll 
try and persist with it, because I’m not getting any problems when I use any of 
the memory managment debugging aids such as zombies and guard malloc, etc. So 
perhaps as you suggest it’s more of a thread safety issue. I can well believe 
it could be, as I’m just exploring using NSOperationQueue for this kind of 
processing, and maybe I’ve just done it wrong.

The app here is only an experiment - if I can get it to work properly it’ll be 
useful experience that I can apply to other situations. So I’m drawing a 
portion of the Mandelbrot set in a view. I tile the view into a number of tiles 
and each one is given the appropriate coordinates and goes away and does the 
calculation work in a block added to an NSOperationQueue. Plotting the 
Mandelbrot set is a good experiment because it is eminently parallisable 
without any co-dependencies between tiles - it just needs to keep track of 
which part of the overall view it belongs to.

When the calculation for a tile is finished, it calls its delegate to tell it 
it has finished. The delegate is the original view. I use 
-performSelectorOnMainThread: to notify the delegate. In response, it takes a 
bitmap that the tile created and filled in, and draws it in the view (well, 
it’s a little more complex. When the delegate of the tile gets the ‘finished’ 
notification, it adds the tile to a dictionary of tiles that can be drawn, 
keyed by a string version of the tile’s coordinates, then it calls 
-setNeedsDisplayInRect: for that tile. When -drawRect is called, it iterates 
through the dictionary drawing tiles that intersect the dirty region of the 
view.) That all works fine - as each tile completes, I see the view plot that 
tile, so gradually the view fills with the complete image.

Pursuing the corruption/thread safety angle, if I set it to just use 1 tile for 
the view, all is well. The spinner spins and the menubar doesn’t block. If I go 
to 2x2 tiles, it’s still OK. Any more than that and the menubar click blocks 
the main thread and the spinner doesn’t animate. Thus the problem is sensitive 
to the number of tasks I add to the NSOperationQueue.

The code that schedules the work is:

if( !self.busy )
{
mBusy = YES;

[[[self class] mandelGeneratorQueue] addOperationWithBlock:^
{
[self createBitmapIfNeeded];

if([self.delegate 
respondsToSelector:@selector(mandelGeneratorWillStartCalculation:)])
[self.delegate 
performSelectorOnMainThread:@selector(mandelGeneratorWillStartCalculation:) 
withObject:self waitUntilDone:NO];

NSUInteger  x, y, xm, ym;
size_t  index;
NSRect  dr = self.destinationRect;

x = xm = NSWidth( dr );
y = ym = NSHeight( dr );

while( y-- )
{
x = xm;

while( x-- )
{
CGFloat ev = [self 
calculateEscapeValueAtX:x y:y];
[self plotEscapeValue:ev atX:x y:y];
}
}

mBusy = NO;

if([self.delegate 
respondsToSelector:@selector(mandelGeneratorDidFinishCalculation:)])
[self.delegate 
performSelectorOnMainThread:@selector(mandelGeneratorDidFi

Re: Spinning the busy indicator

2015-04-30 Thread Quincey Morris
On Apr 30, 2015, at 16:39 , Graham Cox  wrote:
> 
> As I mentioned it’s the spinning busy indicator, which is always 
> indeterminate.

The circular style isn’t always indeterminate, though (I forgot) it looks 
different when it’s not indeterminate.

I just tried forcing an app with a spinning indeterminate progress indicator to 
block its own main thread, and the indicator doesn’t stop animating, regardless 
of whether usesThreadedAnimation is set.

> But when I click in the menubar, the main thread suddenly blocks as given by 
> the stack trace in my previous message. It remains blocked until all of the 
> pending operations complete.

My app also hits a breakpoint at _dispatch_semaphore_wait_slow when I click on 
a menu bar menu, also in the middle of talking to another process via XPC, so I 
don’t think that’s a cause of your problem.

Instead, I suspect you have a memory management error that’s corrupting 
something. Or a thread safety error that’s causing this as a side effect.


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Spinning the busy indicator

2015-04-30 Thread Graham Cox
> Did you set your progress indicator to indeterminate? If not, it’s not going 
> to animate.
> 


As I mentioned it’s the spinning busy indicator, which is always indeterminate.



Something odd is happening, which may or may not have an effect on the busy 
indicator (which is a minor annoyance, but possibly an indication of a much 
more major problem).

When I start my threaded operations, my main loop generally remains responsive 
and as each operation block completes, it updates a view (via the main thread) 
and I see those updates arriving as they complete as intended. I can also 
interact with the view while this is happening, so I can see that events are 
being processed and handled by the view as normal.

But when I click in the menubar, the main thread suddenly blocks as given by 
the stack trace in my previous message. It remains blocked until all of the 
pending operations complete.

My menubar does not have any hooks into my app’s code at all - I’m not even 
implementing menu item validation at the moment. What could the menubar click 
be waiting on that matters? If it’s “normal” that clicking in the menubar 
blocks the main thread while there is an operation queue with unfinished tasks 
that has nothing to do with it, then I think that’s got to be a bug in the OS - 
it just doesn’t make sense.

This is a much more serious issue than the busy indicator animation, but 
something tells me it may be related in some way, though I’m not really seeing 
what it is at the moment.

A general question - given a blocked lock (semaphore_wait_trap), how can I 
discover in the debugger what other threads or code is holding that lock?


—Graham



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Parent/child view controllers: when shall we use it?

2015-04-30 Thread Colas B
Dear cocoa-dev,
When building a simple UIViewController, do I have to use 
addChildViewController: if this VC "owns" other VCs?(By simple VC, I mean I am 
not creating MyCustomNavigationController or something like that; just a "plain 
old" VC)
Imagine for example that I build a view controller (MyCustomVC) and its view 
has a small subview (fbView) for a Facebook logo and a counter. This "facebook 
view" is attached to a view controller (FacebookVC) that is called when fbView 
is touched. So, the FacebookVC definitely needs to be a @property of the 
MyCustomVC.In this situation, should I really use addChildViewController: and 
all the mechanism to declare FacebookVC to be a childController of MyCustomVC? 
My belief is that: NO, in this situation it is not to be use. IMHO, MyCustomVC 
is NOT a container view controller and the usage of child/parent mechanism is 
only for UINavigationController, TabBar, ... or if I want to create such a 
"general" class.
So, am I wrong or am I right ?
Thanks ;-)Colas 
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Yet more new information. Was: Re: Weird UITableView problem

2015-04-30 Thread John Tsombakos
My two cents.. I just tried this on a MacPro, 10.10.3 and Xcode 6 (6.3.1) and 
no matter which device I run in the simulator and scale factor, i can see all 
the items in the list. If looking at the iPad Air, thye all fit on the screen 
without scrolling. Smaller devices I have to scroll the table view.


> On Apr 30, 2015, at 10:44 AM, William Squires  wrote:
> 
> Okay, I've now tried this on Xcode 5 and 6, and on 10.8.5 and 10.10.3. Here's 
> my synopsis:
> 
> * Happens only with UITableView
> * Happens on simulator if set for any device (except iPad?) that has retina 
> display
> * Does not happen if set for a non-retina device.
> * Unknown if this happens on real devices (retina or not).
> * Happens regardless of the scale factor of the simulator display if the Mac 
> does not have a retina display. Unkonwn what happens if your Mac does have a 
> retina display (I don't have one.)
> * Happens with Swift or ObjC project
> * If set for iPad Air, all the rows are "available", plus about 3 to 4 blank 
> ones - this happens regardless of the scale factor (by "available", meaning 
> you can see them, or scroll down to see them.) If the scale factor is set to 
> see all the simulator screen, then the (simulated) UITableView has no 
> scroller and you can see all 20 of the rows, plus 3 blank ones (the rows are 
> there, but have no cell.textLabel.text)
> 
> This is a fairly easy project to duplicate. Just create a "Single View" iOS 
> project with target iOS 7+, for Universal, and either ObjC or Swift. Add a 
> UITableView to the main view, set your view controller to implement 
> UITableViewDelegate and UITableViewDataSource. Connect the outlets to the 
> view controller in IB. Set up some "content" (an array of 20 or so items), 
> and feed it to the UITableView via tableView:numberOfRowsInSection: and 
> tableView:cellForRowAtIndexPath: then set your target device to iPad air, and 
> then again to some iPhone (say, 5s, or 6) that has a retina display.
> 
> If possible, I'd like someone to try this on an actual iPhone, as well as to 
> try it on the simulator on an iMac that does have a retina display.
> 
> 
> On Apr 28, 2015, at 11:45 AM, William Squires  wrote:
> 
>> Thinking this was a Swift problem, I recreated the project, but with ObjC as 
>> the language. I set up the UI the same as with the Swift project. It too, 
>> only shows a subset of the array, only this one shows 15 rows, not 13. 
>> Here's the ViewController.m
>> 
>> //
>> //  ViewController.m
>> //  SimpleObjCTable
>> //
>> //  Created by William Squires on 4/28/15.
>> //  Copyright (c) 2015 William Squires. All rights reserved.
>> //
>> 
>> #import "ViewController.h"
>> 
>> @interface ViewController ()
>> 
>> @property NSArray *dwarves;
>> 
>> @end
>> 
>> @implementation ViewController
>> 
>> - (void)viewDidLoad
>> {
>> [super viewDidLoad];
>> self.dwarves = [NSArray arrayWithObjects:@"Sleepy",
>>   @"Sneezy",
>>   @"Bashful",
>>   @"Happy",
>>   @"Doc",
>>   @"Grumpy",
>>   @"Dopey",
>>   @"Thorin",
>>   @"Dorin",
>>   @"Nori",
>>   @"Ori",
>>   @"Balin",
>>   @"Dwalin",
>>   @"Fili",
>>   @"Kili",
>>   @"Oin", // These are not shown.
>>   @"Gloin",
>>   @"Bifur",
>>   @"Bofur",
>>   @"Bombur",
>>   nil];
>> 
>> // Do any additional setup after loading the view, typically from a nib.
>> }
>> 
>> - (void)didReceiveMemoryWarning
>> {
>> [super didReceiveMemoryWarning];
>> 
>> // Dispose of any resources that can be recreated.
>> }
>> 
>> #pragma mark "UITableView Methods"
>> 
>> -(NSInteger)tableView:(UITableView *)tableView 
>> numberOfRowsInSection:(NSInteger)section
>> {
>> NSInteger theCount = [self.dwarves count];
>> 
>> NSLog(@"theCount = %ld", theCount);
>> return theCount;
>> }
>> 
>> -(UITableViewCell *)tableView:(UITableView *)tableView 
>> cellForRowAtIndexPath:(NSIndexPath *)indexPath
>> {
>> NSLog(@"indexPath.row = %ld", indexPath.row);
>> UITableViewCell *cell = [tableView 
>> dequeueReusableCellWithIdentifier:@"SimpleTableIdentifier"];
>> if (cell == nil)
>> {
>> cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 
>> reuseIdentifier:@"SimpleTableIdentifier"];
>> }
>> cell.textLabel.text = [self.dwarves objectAtIndex:indexPath.row];
>> return cell;
>> }
>> 
>> @end
>> 
>> running it gives me (in the debug console) 4 instances of "theCount = 20", 
>> followed by 15 lines of "inde

Yet more new information. Was: Re: Weird UITableView problem

2015-04-30 Thread William Squires
Okay, I've now tried this on Xcode 5 and 6, and on 10.8.5 and 10.10.3. Here's 
my synopsis:

* Happens only with UITableView
* Happens on simulator if set for any device (except iPad?) that has retina 
display
* Does not happen if set for a non-retina device.
* Unknown if this happens on real devices (retina or not).
* Happens regardless of the scale factor of the simulator display if the Mac 
does not have a retina display. Unkonwn what happens if your Mac does have a 
retina display (I don't have one.)
* Happens with Swift or ObjC project
* If set for iPad Air, all the rows are "available", plus about 3 to 4 blank 
ones - this happens regardless of the scale factor (by "available", meaning you 
can see them, or scroll down to see them.) If the scale factor is set to see 
all the simulator screen, then the (simulated) UITableView has no scroller and 
you can see all 20 of the rows, plus 3 blank ones (the rows are there, but have 
no cell.textLabel.text)

This is a fairly easy project to duplicate. Just create a "Single View" iOS 
project with target iOS 7+, for Universal, and either ObjC or Swift. Add a 
UITableView to the main view, set your view controller to implement 
UITableViewDelegate and UITableViewDataSource. Connect the outlets to the view 
controller in IB. Set up some "content" (an array of 20 or so items), and feed 
it to the UITableView via tableView:numberOfRowsInSection: and 
tableView:cellForRowAtIndexPath: then set your target device to iPad air, and 
then again to some iPhone (say, 5s, or 6) that has a retina display.

If possible, I'd like someone to try this on an actual iPhone, as well as to 
try it on the simulator on an iMac that does have a retina display.


On Apr 28, 2015, at 11:45 AM, William Squires  wrote:

> Thinking this was a Swift problem, I recreated the project, but with ObjC as 
> the language. I set up the UI the same as with the Swift project. It too, 
> only shows a subset of the array, only this one shows 15 rows, not 13. Here's 
> the ViewController.m
> 
> //
> //  ViewController.m
> //  SimpleObjCTable
> //
> //  Created by William Squires on 4/28/15.
> //  Copyright (c) 2015 William Squires. All rights reserved.
> //
> 
> #import "ViewController.h"
> 
> @interface ViewController ()
> 
> @property NSArray *dwarves;
> 
> @end
> 
> @implementation ViewController
> 
> - (void)viewDidLoad
> {
> [super viewDidLoad];
> self.dwarves = [NSArray arrayWithObjects:@"Sleepy",
>@"Sneezy",
>@"Bashful",
>@"Happy",
>@"Doc",
>@"Grumpy",
>@"Dopey",
>@"Thorin",
>@"Dorin",
>@"Nori",
>@"Ori",
>@"Balin",
>@"Dwalin",
>@"Fili",
>@"Kili",
>@"Oin", // These are not shown.
>@"Gloin",
>@"Bifur",
>@"Bofur",
>@"Bombur",
>nil];
> 
> // Do any additional setup after loading the view, typically from a nib.
> }
> 
> - (void)didReceiveMemoryWarning
> {
> [super didReceiveMemoryWarning];
> 
> // Dispose of any resources that can be recreated.
> }
> 
> #pragma mark "UITableView Methods"
> 
> -(NSInteger)tableView:(UITableView *)tableView 
> numberOfRowsInSection:(NSInteger)section
> {
> NSInteger theCount = [self.dwarves count];
> 
> NSLog(@"theCount = %ld", theCount);
> return theCount;
> }
> 
> -(UITableViewCell *)tableView:(UITableView *)tableView 
> cellForRowAtIndexPath:(NSIndexPath *)indexPath
> {
> NSLog(@"indexPath.row = %ld", indexPath.row);
> UITableViewCell *cell = [tableView 
> dequeueReusableCellWithIdentifier:@"SimpleTableIdentifier"];
> if (cell == nil)
>  {
>  cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 
> reuseIdentifier:@"SimpleTableIdentifier"];
>  }
> cell.textLabel.text = [self.dwarves objectAtIndex:indexPath.row];
> return cell;
> }
> 
> @end
> 
> running it gives me (in the debug console) 4 instances of "theCount = 20", 
> followed by 15 lines of "indexPath.row = 0" up to "indexPath.row = 14" (15 
> total, which corresponds to the comment in the initialization line for 
> dwarves = NSArray... line above.) In both cases (the Swift project, and the 
> ObjC project) I use the default view (with the size class w:any, h:any) and 
> pin the UITableView to the edges of the parent view.
>  Now I'm totally lost as to why only a limited subset of the rows are being 
> shown, especially given that tableView:numberOfRowsInSection: consistently 
> return