Every now and then, I notice that I'm using a block to iterate over a collection without writing to any shared data or causing any side effects. I consider adding in an NSEnumerationConcurrent option, then decide against it as I don't really understand when it's worth using.
So I've got a specific question, and a more general one.
First question: Here's a maybe slightly contrived example of using a block to do something trivial concurrently:
CGFloat GetAverageHeight(NSArray* people)
{
NSUInteger count = [people count];
CGFloat* heights = malloc(sizeof(CGFloat) * count);
[people enumerateObjectsWithOptions: NSEnumerationConcurrent usingBlock:
^(id person, NSUInteger idx, BOOL* stop)
{
heights[idx] = [person height];
}];
CGFloat total= 0.0;
for (size_t i = 0 ; i < count ; i++) total += heights[i];
free(heights);
return total / count;
}
Ignoring the fact that a non-concurrent enumeration could have just summed the height directly, without the need for calling malloc or the second half of the function, is there any point using NSEnumerationConcurrent here? Does the overhead of using GCD (or whatever NSEnumerationConcurrent does in the background) negate the gain of getting a trivial property concurrently? How much less trivial does the block's work need to get before it's worth using NSEnumerationConcurrent?
Second question: More generally, should I consider concurrency to be something I should use when I see an opportunity to do so (rationale: presumably the point of these APIs is that they make concurrency less of a special case and more part of the general makeup of a program), or just an optimisation that I should only use if I've found a specific performance issue and believe that concurrency is the answer (rationale: bugs in concurrent code are a nightmare to track down)?