I'm a beginner in xcode and iphone iOS development while debugging the xcode it shows Thread1,Thread2,Thread3,Thread4 what these threads meant? and how it is useful in debugging can some explain?
For the purposes of debugging your own app, you really only need to worry about Thread1, or at least until such point that you start writing concurrent code (see Concurrency Programming Guide).
A thread is basically a particular path of execution of code. Thread1 is the "main thread", the one where your app does its basic operations, all of the user interface code, etc. When you start getting into more sophisticated programming, you might employ concurrency, where you send time consuming operations to a background thread/queue so that it doesn't adversely affect the user experience which is happening on the main thread.
The threads 2, 3, 4, etc. in your question, though, are system generated threads and not ones you generally need to concern yourself with. Only worry about the main thread and, if and when you get into writing concurrent code, those threads to which you are explicitly adding operations.
Related
Pretty simple question that I haven't found anywhere in documentation or tutorials on GCD: What happens if I'm submitting work to queues faster than it's being processed and removed? I'm aware that GCD queues have no size limit, would work just pile up until the program runs out of memory? Is there any way to properly handle this situation?
What happens if I'm submitting work to queues faster than it's being processed and removed?
It depends.
If dispatching tasks to a single/shared serial queue, they will just be added to the queue and it will process them in a FIFO manner. No problem. Memory is your only constraint.
If dispatching tasks to a concurrent queue, though, you end up with “thread explosion”, and you will quickly exhaust the limited number of worker threads available for that quality-of-service (QoS). This can result in unpredictable behaviors should the OS need to avail itself of a queue of the same QoS. Thus, you must be very careful to avoid this thread explosion.
See a discussion on thread explosion WWDC 2015 Building Responsive and Efficient Apps with GCD and again in WWDC 2016 Concurrent Programming With GCD in Swift 3.
Is there any way to properly handle this situation?
It is hard to answer that in the abstract. Different situations call for different solutions.
In the case of thread explosion, the solution is to constrain the degree of concurrency using concurrentPerform (limiting the concurrency to the number of cores on your device). Or we use operation queues and their maxConcurrentOperationCount to limit the degree of concurrency to something reasonable. There are other patterns, too, but the idea is to constrain concurrency to something suitable for the device in question.
But if you're just dispatching a large number of tasks to a serial queue, there's not much you can do (other than looking for parallelism opportunities, to make efficient use of all of CPU’s cores). But that's OK, as that is the whole purpose of a queue, to let it perform tasks in the order they were submitted, even if the queue can't keep up. It wouldn’t be a “queue” if it didn’t follow this FIFO sort of pattern.
Now if dealing with real-time data that cannot be processed quickly enough, you have a different problem. In that case, you might want to decouple the capture of the input from the processing and decide how to you want to handle it. E.g. if you can't keep up with real-time processing of a video, for example, you have a choice. Either you start dropping frames or process the data asynchronously/later. You just have to decide what is right for your use case. We cannot answer this question in the abstract.
I am trying to understand under what circumstances and how iOS may throttle my application threads due to excessive CPU consumption. The results I'm getting are kind of strange.
I have an application with OpenGL / GLKViewController rendering a view and a separate logic thread, started in the background using NSThread.detachNewThreadSelector, performing calculations. I find that if I (for purposes of discussion) let my computation thread run flat out as fast as it can, iOS quickly throttles it down. e.g. I monitor the FPS of both the view and my thread and I see that the view maintains e.g. 60fps and my logic thread is humming along but then suddenly drops after a few seconds.
So that makes sense to me that perhaps iOS tries to limit thread consumption. What is weird is that it doesn't just slow down gradually but it seems to "quantize" my logic thread's FPS at approximately some multiple of the GPU frame rate (i.e. 30 or 60fps)!
Now, keep in mind that there is no synchronization between these threads and the logic loop is self contained hard loop equivalent to while(true) so I have no idea how it's even possible for iOS to accomplish this magic unless it is somehow aware of my top level loop and interjecting itself into it.
In case you don't believe me that there is no synchronization point I will tell you that I have created a test case that literally just has an empty GLKViewController loop and an dumb logic thread that churns some numbers and it exhibits the behavior. Screenshots are below and I can post the code if anyone is interested.
The screenshots below are for two different "loads" of the logic thread, printed at intervals of a second, running on an iPad Air with iOS 8.
What's even stranger is - sometimes setting a lower preferred GLK frame rate (e.g. 30fps) can actually make my logic thread run slower. I'd have expected that reducing the work done by the GPU would free up (resources / heat dissipation) and reduce the need for throttling, but it doesn't always seem to be the case.
Does anyone have an explanation for this behavior? Is it documented? Thanks.
EDIT: My only guess at this point is that if the GPU runs to hot they shut down the second core and migrate threads back to the first... and then somehow thread prioritization accounts for the implicit synchronization, although I still can't envision exactly how this happens.
I'm developing an iOS application right now, and I have a quite high CPU usage. So I decided to profile it a bit.
With Xcode 5 things became easy, and I can see that "Thread #25" is using quite a lot of CPU. Sadly this thread is not named, and my app has external dependencies, so I don't have a means to add names for each thread.
tl;dr: How can I know who spawned this "Thread #25" ?
XCode 5 present CPU usage report, including processing break up of each running thread. That's good and helpful to some extent.
But, can we give these threads programmatically some names so that it's easy to identify them? These threads are spawned by OS when my app schedule few NSTimers, NSOperation, NSURLConnection etc but I can't exactly map or identify threads shown in CPU report with their respective operations.
As you can see in the screenshot below, most of these threads are "Unnamed" making it difficult to identify the associated operations.
Also, in general, what is the best way to comprehend this CPU report? Any suggestions please.
I'm using this tiny class to mark threads I need to identify in CPU monitor:
https://github.com/deszip/APThreadMarker
Just call:
[APThreadMarker markCurrentThreadWithName:#"thread 1"];
inside start method of your NSOperation subclass and thread created for this NSOperation will have provided name.
I'm using NSOperationQueue to manage a phase of an iOS application which is quite long so I would like to manage it asynchronously. Inside that phase I allocate big arrays in C by using directly calloc functions.
With big I mean a 1024x256 bidimensional array of floats and similar things.
If everything resides on the main thread than the app locks up while computing but everything goes fine, if, instead, I move the heavy part to a NSInvocationOperation then I got many strange results, with debugger sometimes I get a strange message in console stating
No memory available to program now: unsafe to call malloc
so I was wondering if threads managed by an operation queue have some different restrictions compared to main thread, and in case what is better to do to get around this issue.
There's no restrictions that I know of.. however, you may be hitting the edge of available RAM. Since iOS doesn't do virtual memory, when memory gets low, it'll send a warning to other apps to free up RAM. That may be the source of your issue.
Use instruments to profile how much RAM you're using. If it's more than about 20MB or so, you're probably in danger of being terminated due to excessive memory usage anyway.