NSOperation Queue vs NSUrlConnection async - ios

I have an app that is downloading several photos off of Flickr. Right now, all the photos are downloaded with a custom NSOperation class run on an NSOperationQueue.However, I have heard about NSUrlConnection async being more efficient, and was wondering which is better of this situation? Or, is there a third option that's even better than these two?
The custom NSOperation simply calls [NSData dataWithContentsOfURL:] many times on different photos.

Using an approach which utilizes a subclass of NSOperation and which encapsulates NSURLConnection which is used in asynchronous mode (implementing the delegate protocols) is likely the most efficient, iff you additionally consider these aspects:
Ensure that the NSOperation subclass handles the delegate methods quickly, and that the underlaying thread (or the queue) will NOT be used to process the response data. Ideally, the delegate methods pass over the partial response data to another queue or thread where they are processed (note: image data may be preloaded on a background thread or a queue!).
The reason for this is that, the sooner the network operation finishes, the more requests can be performed per time. The network NSOperation shall be put into a NSOperationQueue whose max concurrent operations is set to 1, or 2. Rarely to 4 or higher. This setting depends on whether the server supports pipelining, and on the speed of the connection. Name that queue "Network bound queue".
The "data process" (preload image data) task is ideally a subclass of NSOperation, too. Likewise, the "data process" operations should be queued in a CPU bound NSOperationQueue. Per default the max concurrent operations of a NSOperationQueue is already suitable for CPU bound operations.
If you want to save the data to disk, again, ideally you create a NSOperation and queue those disk operations in a "disk bound queue". On devices, this seems not necessary, but if you have still such oldish "disks" - than it makes sense to set the number of max concurrent operations to the number of independent heads of the disk. ;)
Well, this all may make only a difference, when the connection is really fast and if you are able to process that much data in the same time. We are talking about 5 Mbyte per second on a device, and probably 25 Mbyte per second on a lab top.

Try these tutorials may help you:
http://maniacdev.com/2010/03/easier-threading-with-nsoperation-for-better-performance
http://www.raywenderlich.com/19788/how-to-use-nsoperations-and-nsoperationqueues
http://www.icodeblog.com/2012/10/19/tutorial-asynchronous-http-client-using-nsoperationqueue/
OR
If you are downloading photos and showing them in table cell, then you can use Lazy loading images.

I would recommend using AFNetworking (AFNetworking on Github)
which has built-in functionality for queuing operations.
If you only use it to load images that need to be displayed in a table view cell, you could use the AFNetworking category on UIImageView to load these images asynchronously.

Related

Concurrent execution and NSOperationQueue management

I have two questions about multi-threads in iOS
if I want to simulate 100 concurrent API call, which means these 100 API calls start at the same time, how should I do it?
Like if something like this
for i in 0..<100 {
//Start API call
}
or add 100 operations in one operationQueue and set max concurrent over 100, start the operations in the queue
all these should means start the API call one by one, so how to start them at the same time? just like add 100 operations and start together
How to add and monitor NSURLSessionDataTask objects in operationQueue? Like use waitUntilAllOperationsDone() method for multiple NSURLSessioNDataTask Objects.
I'm using something like
dispatch_group_enter(group)
session.dataTaskWithCompletion({
dispatch_group_leave(group)
})
dispatch_group_notify()
I'm wondering if this could be implemented in NSOperationQeue, it seems every thread created by NSURLSessionDataTask is randomly created by system so how to monitor it in NSOperationQueue?
Whether you start these 100 tasks by just calling some asynchronous method or using an operation queue, the effect is similar, that they won't technically all start at exactly the same time, but they should (with a few caveats) start closely enough to each other such that, assuming the asynchronous API call doesn't return instantaneously, you'll certainly have them running at the same time.
Note, if the API is using NSURLSession, you may have to adjust the httpMaximumConnectionsPerHost of your NSURLSessionConfiguration. Usually it's constrained to some reasonable value, and if you want 100 concurrent tasks (more than you'd ever want to use in a production environment), you may have to adjust this setting.
You ask a few questions about operation queues. There's little benefit, IMHO, in introducing operation queues into this discussion. In fact, one of the main use cases for operation queues is to achieve the precise opposite, when you don't want them all running concurrently, but rather want to constrain the concurrency to something reasonable (e.g. 4 at a time). So operation queues might be part of your eventual production solution, but don't introduce it solely for the sake of trying to run a lot of requests at the same time.
Also note, when trying to run a bunch of asynchronous tasks on operation queue, you can't just addOperationWithBlock or add an NSBlockOperation. You have to make an asynchronous custom subclass of NSOperation that sets the isAsynchronous flag and does the necessary KVO of isFinished and isExecuting. It's not hard, but it's enough work that it's not something I'd introduce without a compelling need.
Regarding dispatch group "notify" vs operation queue, yes, you can achieve something similar using operation queues. You can just create some "completion" operation which is dependent upon all of the other operations finishing and add that to some queue after all of the other operations have been queued.

Swift, number of threads in app

I am making an app for website. I use JSON to get data. I want to load all posts in threads (1 post - 1 thread). How many threads I can make? Should I control the number of threads?
With Cocoa you usually don't work with Threads directly. Grand Central Dispatch (GCD) is an API that handles this for your. You just have to partition your task into small managable chunks, dispatch them onto a background queue and the rest is handled for you. You don't need to worry about creating threads, how many are currently running etc. When you dispatch enough work on one (or possibly more) queues, the CPU is going to run at maximum load.
You can also use NSOperationQueue, which has the ability to throttle the execution to some extend or cancel currently running tasks (not possible with GCD).
Unless you are doing anything unusual there is no need to use NSThread directly. Use GCD when you just need to perform a simple small task asynchronously. Use NSOperationQueue when you need more control, like cancelling submitted tasks or setting priorities. It's API is also a bit higher level and in Objective-C. GCD is a C level API, so for example it can't catch ObjC-Exceptions. NSOperationQueue uses GCD internally, so both should work equally well.

What is the difference between 'thread' and 'queue' in iOS development? [duplicate]

This question already has answers here:
Use of the terms "queues", "multicore", and "threads" in Grand Central Dispatch
(3 answers)
Closed 8 years ago.
I am new to iOS development. Now I am quite confused about the two concepts: "thread" and "queue". All I know is that they both are about multithread programming. Can anyone interpret those two concepts and the difference between them for me?
Thanks in advance!
How NSOperationQueue and NSThread Works:
NSThread:
iOS developers have to write code for the work/process he want to perform along with for the creation and management of the threads themselves.
iOS developers have to be careful about a plan of action for using threads.
iOS developer have to manage posiable problems like reuseability of thread, lockings etc. by them self.
Thread will consume more memory too.
NSOperationQueue:
The NSOperation class is an abstract class which encapsulates the code and data associated with a single task.
Developer needs to use subclass or one of the system-defined subclasses of NSOperation to perform the task.
Add operations into NSOperationQueue to execute them.
The NSOperationQueue creates a new thread for each operation and runs them in the order they are added.
Operation queues handle all of the thread management, ensuring that operations are executed as quickly and efficiently as possible.
An operation queue executes operations either directly by running them on secondary threads or indirectly using GCD (Grand Central Dispatch).
It takes care of all of the memory management and greatly simplifies the process.
If you don’t want to use an operation queue, you can also execute an operation by calling its start method. It may make your code too complex.
How To Use NSThread And NSOperationQueue:
NSThread:
Though Operation queues is the preferred way to perform tasks concurrently, depending on application there may still be times when you need to create custom threads.
Threads are still a good way to implement code that must run in real time.
Use threads for specific tasks that cannot be implemented in any other way.
If you need more predictable behavior from code running in the background, threads may still offer a better alternative.
NSOperationQueue:
Use NSOperationQueue when you have more complex operations you want to run concurrently.
NSOperation allows for subclassing, dependencies, priorities, cancellation and a supports a number of other higher-level features.
NSOperation actually uses GCD under the hood so it is as multi-core, multi-thread capable as GCD.
Now you should aware about advantages and disadvantages of NSTread and NSOperation. You can use either of them as per needs of your application.
Before you read my answer you might want to consider reading this - Migrating away from Threads
I am keeping the discussion theoretical as your question does not have any code samples. Both these constructs are required for increasing app responsiveness & usability.
A message queue is a data structure for holding messages from the time they're sent until the time the receiver retrieves and acts on them. Generally queues are used as a way to 'connect' producers (of data) & consumers (of data).
A thread pool is a pool of threads that do some sort of processing. A thread pool will normally have some sort of thread-safe queue (refer message queue) attached to allow you to queue up jobs to be done. Here the queue would usually be termed 'task-queue'.
So in a way thread pool could exist at your producer end (generating data) or consumer end (processing the data). And the way to 'pass' that data would be through queues. Why the need for this "middleman" -
It decouples the systems. Producers do not know about consumers & vice versa.
The Consumers are not bombarded with data if there is a spike in Producer data. The queue length would increase but the consumers are safe.
Example:
In iOS the main thread, also called the UI thread, is very important because it is in charge of dispatching the events to the appropriate widget and this includes the drawing events, basically the UI that the user sees & interacts.
If you touch a button on screen, the UI thread dispatches the touch event to the app, which in turn sets its pressed state and posts an request to the event queue. The UI thread dequeues the request and notifies the widget to redraw itself.

NSOperationQueue, concurrent operation and thread

I'm developing a sort of fast image scan application.
In the -captureOutput:didOutputSampleBuffer:fromConnection: method I pick up the CVPixelBuffer and add them into an NSOperation subclass. The NSOperation takes the buffer and transform it into an image saved on the filesystem.
The -isConcurrent method of NSOperation returns YES. After the operation is created, is added to an NSOperationQueue.
Everything runs fine except for one issue that is affecting the scan frame rate.
Using time profiler I've found that some of the NSOperation are run on the same thread of the AVCaputureVideoOutput delegate that I've created:
dispatch_queue_t queue = dispatch_queue_create("it.CloudInTouchLabs.avsession", DISPATCH_QUEUE_SERIAL);
[dataOutput setSampleBufferDelegate:(id)self queue:queue];
When an operation is running on the same thread of the AV session queue, it affects the frame rate, it happens only with some them, probably GCD is deciding under the hood dispatching on active threads. The only method I've found to solve that issue, is to create a separate thread and pass it to the the single operations forcing them to run on it.
Is there another way, to force operations run on a different thread?
[EDIT]
Following the #impcc suggestions I made some test.
Results are pretty interesting even if sort of inconsistent.
Test platform is an iPhone 5 connected in debugging mode through an MBP with 16gb of RAM quad core i7. The session has a 60fps output tested with the algorithm in RosyWriter apple sample code.
AVSession queue sync targeted to high priority queue
26 fps where sometimes the thread of the queue is shared with the one
of the operation. The time taken inside the delegate methods has an
average of 0.02s
14 fps with a thread created just for the operations, if the main
method is not called on this thread, the start will be forced to perform
on that specific thread. This thread is create one time and kept
alive with a dummy port.. The time taken inside the delegate is
0.008.
AVSession queue concurrent targeted to high priority queue
13.5 fps where sometimes the thread of the queue is shared with the one of the operation. The time taken inside the delegate methods has
an average of 0.02s, substacially equal to the counterpart with sync
queue.
14 fps with a thread created just for the operations, if the main
method is not called on this thread, the start will be forced to perform
on that specific thread. This thread is create one time and kept
alive with a dummy port. The time taken inside the delegate is
0.008.
Conclusion
Concurrent or serial queue doesn't seems to make a big difference, however concurrent for me is not ok cause of the timestamps that I need to take to preserve the sequence of single picture. The fact that is surprising me is the frame drop using an ad-hoc thread, even if the time taken inside the delegate method is considerably less, the frame rate drops about 10fps. Just trusting in GCD the frame rate is better but the delegate methods takes more than 2 times to finish, this probably due to the fact that sometimes the AV queue is used by also the nsoperations. I can't really get why the time taken inside the delegate doesn't seems to be correlated to the fps. Shouldn't be the faster the better?
By further investigations it really seems that what is stealing time si in the process of adding and probably executing operation in queue.
I think you might be misunderstanding the meaning of isConcurrent. This is totally understandable, since it's incredibly poorly named. When you return YES from -isConcurrent what it really means is "I will handle any concurrency needs associated with this operation, and will otherwise behave asynchronously." In this situation, NSOperationQueue is free to call -start on your operation synchronously on the thread from which you add the operation. The NSOperationQueue is expecting that, because you've declared that you will manage your own concurrency, that your -start method will simply kick off an asynchronous process and return right away. I suspect this is the source of your problem.
If you implemented your operation by overriding -main then you almost certainly want to be returning NO from isConcurrent. To make matters more complicated, the behaviors associated with isConcurrent have changed over the years (but all that is covered in the official docs.) A fantastic explanation of how to properly implement a returns-YES-from-isConcurrent NSOperation can be found here.
The way I'm reading your question here, it doesn't sound like your NSOperation subclass actually needs to "manage its own concurrency", but rather that you simply want it to execute asynchronously, "on a background thread", potentially "concurrently" with other operations.
In terms of assuring the best performance for your AVCaptureVideoDataOutputSampleBufferDelegate callbacks, I would suggest making the queue you pass in to -setSampleBufferDelegate:queue: be (itself) concurrent and that it target the high-priority global concurrent queue, like this:
dispatch_queue_t queue = dispatch_queue_create("it.CloudInTouchLabs.avsession", DISPATCH_QUEUE_CONCURRENT);
dispatch_set_target_queue(queue, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0));
[dataOutput setSampleBufferDelegate:(id)self queue:queue];
Then you should make the delegate callback methods as lightweight as possible -- nothing more than packaging up the information you need to make the NSOperation and add it to the NSOperationQueue.
This should ensure that the callbacks always take precedence over the NSOperations. (It's my understanding that NSOperationQueue targets either the main queue (for the NSOperationQueue that's associated with the main thread and run loop) or the default priority background queue.) This should allow your callbacks to fully keep up with the frame rate.
Another important thing to take away here (that another commenter was getting at) is that if you're doing all your concurrency using GCD, then there is only one special thread -- the main thread. Other than that, threads are just a generic resource that GCD can (and will) use interchangeably with one another. The fact that a thread with a thread ID of X was used at one point to service your delegate callback, and at another point was used to do your processing is not, in and of itself, indicative of a problem.
Hope this helps!

Select proper multithreading technique in iOS

I am confused on where to use which multithreading tool in iOS for hitting services and changing UI based on service data,
firstly I got accustomed to using NSURLConnection and its delegates, used didreceiveresponse, didreceivedata etc delegates to achieve the task
secondly I learned and used GCD to hit services and update the UI from within the block code
Now I am learning to use performSelectorInBackground() to do work in background thread
Clearly confused on which tool to use where?
NSURLConnection with delegate calls is "old school" way of receiving data from remote server. Also it's not really comfortable to use with few NSURLConnection instances in a single class (UIViewController or what not). Now it's better to use sendAsynchronousRequest.. method with completion handler. You can also define on which operation queue (main for UI, or other, background one) the completion handler will be run.
GCD is good for different tasks, not only fetching remote resources with initWithContentsOfURL: methods. You can also control what type of queues will receive your blocks (concurrent, serial ,etc.)
performSelectorInBackground: is also "old school" way of performing a method in background thread. If you weren't using ARC, you'd need to setup separate autorelease pool to avoid memory leaks. It also has a limitation of not allowing to accept arbitrary number of parameters to given selector. In this case it's recommended to use dispatch_async.
There are also NSOperationQueue with NSOperation and its subclasses (NSInvocationOperation & NSBlockOperation), where you can run tasks in the background as well as get notifications on main thread about finished tasks. IMHO They are more flexible than GCD in a way that you can create your own subclasses of operations as well as define dependencies between them.
The most important thing is, that you never change UI anyway in another thread except the main thread.
I think, that all points you mentioned use the same technique in the background: GDC. But I'm not sure of that.
Anyway it doesn't matter which tool you should use in terms of threading.
It's rather a question of your purpose. If you wan't to fetch an small image or just few data you can use contentsOfURLin a performSelectorInBackground() or a GDC dispatch block.
If it's about more data and more information like progress or error handling you should stick with *NSURLConnection`.
I suggest using GCD in all cases. Other techniques are still around but mainly for backward compatibility.
GCD is better for 3 reasons (at least):
It's extremely easy to use and the code remains very readable because of the use of blocks
It is lower level than things like NSOperation so it is much faster when you need high performance multi threading
It's lightweight and non-intrusive so your code doesn't have to change substantially when you want to add thread management in the middle of a method.

Resources