Multithreading the pathfinding in a tower defense game - iphone

I'm making a tower defense game and I'm stuck at the multithreading of the pathfinding. If i don't make the pathfinding an NSInvocationOperation then there is an increasing pause in the rendering the more fiends and towers i have.
However i cannot solve the "locking" issue. I get frequent crashes about enumerating my fiend NSMutableArray while mutating it. If i instead try to lock the enumeration in the main thread while pathfinding is being done, the game still locks up and i have lost the whole point of the multithreading..
How do i solve this kind of issue?

Think about what happens when another tower is placed. Enemies will either have to consider the new tower in their path decision or not. Determining those new paths takes time, and collectively will cause a delay no matter what multithreading solution you choose. The problem ultimately lies in your path-finding algorithm. If it is taking too long to calculate then you're going to see that delay.
Take a look at ways you can avoid having to find those paths. Does dropping a tower at location (x,y) effect all enemies? Can you calculate only a few paths and enemies choose which one to follow? Can you cache paths and reuse parts that have already been calculated (like a how river flows with branching tributaries)?
I think there are many ways you can reduce the impact of path finding in your problem.

Threading would definitely help with delay tactics such as starting to move in the general direction before the path finding is complete.
Edit: I missed that you said it was your fiend array that was causing problems. I think your best bet is looser coupling. Try not to make the path finder dependent on your fiend array. Send it a copy of just the data it needs for one fiend (starting position, goal position, etc.) and get an array of points back. Don't give it access to the whole array or even a reference to any fiend object.

I agree with Tim Rupe that optimizing pathfinding would probably be helpful.
Another (additional) approach would be separate your 'current' array of paths from your 'next' array of paths. So, the game continues with the current array of paths, while the next array is being calculated in another thread. This avoid the deadlocking, crashing, etc.
Then, at some well-defined point, you swap in the 'next' for the 'current' (protected by a mutex or whatever). Basically, you are always dealing with snapshots - but you have control over the rate at which snapshots are swapped (provided your pathfinding algorithm is not too slow).

Sending mutable data across thread boundaries is a good recipe for problems. You should always use NSArray, NSString, NSSSet, etc, instead of their mutable subclass when sending an object to another thread. This simple rule makes multithreading so much more pleasant.
Thankfully all collection classes implements the NSCopying protocol and thus have a nifty -[copy] method that return s an immutable copy of itself.
Next thing you need to decide is what to do if you mutate the original array. Sould you:
Just enqueue a new pathfinder operation?
Discard the current pathfinder operation, and start a new?
Option 1. to just add a new operation is easiest, but may/will waste time if your original arrays are mutated frequently.
Option 2. require some more work on your part. More specifically:
You must hold onto the last operation so that you can send a -[NSOperation cancel] message to it. Or alternatively if you have a queuededicated to only pathfinding that you can cancel all operations on it using [NSOperationQueue cancelAllOperations].
You should bail out early from your operations if they are cancelled. This requires you to subclass NSOperation, you can no longer just use NSInvocationOperation as-is.
Your NSOperation subclass implementation should look something like this:
#implementation CWPathfinderOperation
-(id)initWithFiends:(NSArray*)fiends delegate:(id<CWPathfinderOperation>)delegate {
self = [super init];
if (self) {
self.fiends = fiends;
self.delegate = delegate;
}
return self;
}
-(void)main {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
while (notDone) {
if ([self isCancelled]) goto bailOut;
// Do smallpart of work
}
[self.delegate performSelectorOnMainThread:#selector(pathfinderOperatioDidFindPaths:)
withObject:result
waitUntilDone:NO];
bailOut:
[pool release];
}
#end

Related

Cocos2d: usage of references vs getChild performance

I am unsure on which approach will give me a better performance:
I have a GameScene class in which I tend to allocate a objects and then add them as childs to the class with a tag. This approach is used in many examples I studied but I am not sure if it is the best when I need to frequently access to child objects (e.g. update a score label in the GameScene). In those cases I am wondering if it would be a better approach in terms of performance to declare a pointer to those frequently used object and use it to access the object instead of getting the child by tag.
Is it more efficient to use getChildByTag or accessing those objects via their pointer?
As example I provide a label that I frequently update during the game, e.g. it could be the score label:
#interface GameScene : CCLayer
{
CCLabelTTF *frequentlyUsedLabel;
}
//Implementation
-(id) initWithId:(int)sceneId
{
if ((self = [super init]))
{
//..code
frequentlyUsedLabel = [CCLabelTTF labelWithString:#"Hearths:" fontName:#"Arial" fontSize:20];
[self addChild:frequentlyUsedLabel];
}
}
Write code that is easy to maintain.
Anything worth optimizing is worth measuring.
Time how long it takes to render a frame using both methods. Ask yourself if it matters.
The extra memory overhead is a little more difficult to measure (in particular, Cocos2D might be using a clever allocator that is more efficient if your CCLayer subclass doesn't declare any extra ivars). My take is that 4 bytes is the amount of memory used by a single pixel.
With UIKit, I personally find it much easier to use ivars than to worry about tag uniqueness (especially when reusing code in different apps or using a view in multiple places). This is especially the case with ARC, since you no longer have to worry about getters/setters/retain/release.

ways to bind model classes in Objective-C

(I hope someone will correct my terminology if I get it wrong -- I'm still sorting out terms)
I have a series of classes in my model. I need to get some data from a url (SatDataGetter) and combine it with a location and date specific calculation (DayCalculater), do some further calculations (DataMixer), some interpretation to make it user-understandable (Advisor), and then present the results in a view.
There are issues with setting up the dependencies and making sure that, for instance, the SatDataGetter has valid data before it gets called by DataMixer, before it gets called by.. you get the idea. Of course, if the location changes, I need to update the whole thing from the bottom up. At minimum I have to get a message to the ViewController and the Advisor to reload their data.
The research I've done suggests that NSNotification is one way to go, but I could also try Key-Value Observing. I found some old posts (2009) on KVO, suggesting some possible problems and difficulties with debugging. http://www.mikeash.com/pyblog/key-value-observing-done-right.html
What's the preferred method? What are the issues I should be considering in deciding --
For instance:
The SatDataGetter essentially returns a single number. KVO seems like a reasonable way for DataMixer to keep track of what that value is, but I don't think I want all the parent classes to be doing KVO on the dependent variables.
When do you choose an NSNotification and when KVO?
The difference between NSNotifications and Key-Value Observation is largely one of coupling, but there are also performance implications.
Anyone can subscribe to your NSNotifications. All they need to know is the string/key that you notify under. They don't need to know anything about your classes/object-graph etc. So when you want to notify a world that doesn't know about the details of your class, NSNotification is the way to go. For instance, if you're vending a framework to other developers, it's probably better to notify by NSNotification than by exposing the internals of your framework to the degree that might be necessary to allow consumers to Key-Value Observe your objects.
In order to KVO observe an object you first have to be able to get a reference to it, which is not strictly true of NSNotifications (but usually happens to be true in my experience.) Secondly, you need to know enough about the implementation to know what to observe. With NSNotification the notifier need only publish a notification string/key. With KVO, you need to know the name of a property of the object. Sure, someone could publish static strings and tell you "you can KVO me for these properties" but that effectively becomes an API contract that may be harder to maintain going forward. (Say, for instance, you want to remove that property in a future version -- then you have to rig up other things to continue to send those notifications and provide values when people call valueForKey: -- in short, once you do that, you can never change that property.)
The other thing to remember with these various degrees of coupling is that with KVO, there can be an expectation that the observer knows about the details of your classes/objects. After all, they're registering a very specific interest in your object; they claim to know what that means -- how it works. Therefore you might expect them to be sensitive to the performance implications. With NSNotifications, the consumer can observe your notification knowing virtually nothing about you, and may not be aware of performance implications of how they act in response to the notification.
The drawback shared between the two approaches is that, absent extra work, they're both delivered synchronously. The notifying object is at the mercy of what the observer chooses to do (synchronously) when it receives the notification. The two mechanisms differ here in that for NSNotification it's quite easy for the notifying object to use performSelector:afterDelay: to cause the notification to be sent "asynchronously" (with respect to the call that spawns the notification) on the next pass of the run loop (see also NSNotificationQueue). This is not as readily possible with KVO. This difference alone may be crucial in certain situation.
Generally, I find that the loose coupling of NSNotification lends itself to events that are either large-granule (i.e. potentially represent a large group of changes) or relatively infrequent. KVO notifications are, by their very nature, fine-grained. You're explicitly observing a change of a single property (per registration) on a single object. This has the potential to blow up the number of registrations and the number of notifications. Every observation has a performance cost to it.
Another shared drawback to both of these is debuggability. I mentioned in a comment above that KVO can be a challenge to debug, and it shares that challenge with NSNotificationCenter as well.
The key difference between these two and the delegate pattern is that delegate relationships are typically 1:1 (one delegate.) (Sure, you could have an array of delegates, but that's pretty uncommon, and debatably an anti-pattern.) NSNotification and KVO are both inherently 1:N (many observers.)
In closing, I always like to say, "use the highest level of abstraction that will get the job done." If you only need a 1:1 relationship, use a delegate. For 1:N notifications, if an NSNotification will work -- in other words if the desired coupling is low and/or the notifications are large-grained or infrequent, use NSNotifications. If the coupling is tight, or the need is fine grained, use KVO. Also remember that you can adapt a delegate pattern from 1:1 to 1:N by having the delegate send NSNotifiations. With NSNotifications and KVO, you can't really control who observes you or how many observers you have.
I generally use KVO to watch for changes to properties within an object - so, instead of overriding the setter for an object, I'll use KVO to fire the observe method on a change, and then call other methods at that point.
I tend to use NSNotifications to inform other objects that something has happened. In your example, I may have a singleton to handle the location stuff, and then send a notification when userLocation changes.
And, of course, you can also use the delegate pattern to notify another object of a change.
These aren't hard and fast rules though...I'm wont to change on a whim!
You probably don't need any of those strategies, you can probably get by with some sort of delegate hierarchy. If you are using core location or any other service that you can't get reliable data from synchronously, then you can use that as your starting point... if you have 2 such services, (getting http data, and Core Location for instance), Then you may have to perform some caching and delegation... i.e. last best location + current http data get pushed to the view.
How about NSOperations?
// create two ops, and set a dependency
DownloadOp *op = [[Download alloc] initWithURL:#"http://xxx"];
CalculationOp *op = [CalculationOp new];
[calculationOp addDependency:downloadOp];
// ... more steps
// add to the queue
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:downloadOp];
[queue addOperation:calculationOp];
// runloop for unit testing
while(!parserOp.isFinished) {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:1]];
}
Inside the -[CalcuationOp start]:
// get the result from the previous step
id obj = [self.dependencies objectAtIndex:0];
if ([obj isKindOfClass:[DownloadOp class]]){
DownloadOp *op = (DownloadOp*) obj;
self.input = op.output;
}
Inside the AdvisorOp:
// update the GUI from the main thread
dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_async(mainQueue,^{
// update some UI element
});
Then listen to location updates on the CLLocationManager delegate to start the whole thing. I'm using this with the logic decoupled from the operations so I can unit test each part alone.
Benefit: it runs asynchronously and you can cancel the operations on the queue at any time. Downside: you have to learn NSOperation.

How can I maintain a global cache of objects? (or a NSMutableSet w/o retaining contents)

I have an iPhone app which deals with a subset of 25,000 places at any given time.
I'd like to maintain a cache of places so that I know that if one part of my application updates a place, every other part that knows about that place sees the update.
My naive implementation is create an NSMutableSet to store references to the cached places.
Methods that find new places will first check the cache and return the cached object or if the place isn't in the cache, they will create a new place object and add it to the cache.
The problem is how do I release objects that are no longer needed?
The NSMutableSet will retain the place so the retainCount will never go to zero and dealloc will never be called.
Is there a kosher method to handle the release scenario? Is there some other pattern for doing this that I'm not aware of.
(and CoreData is not an option at this point, but I understand that it handles this).
Thank you,
On the desktop you can do this with NSPointerSet, on the iPhone it is a bit more difficult.
You can use CoreFoundation to create a non-retaining set if you really want to:
//Default callbacks
CFSetCallBacks callbacks = kCFTypeSetCallBacks;
//Disable retain and release
callbacks.retain = NULL;
callbacks.release = NULL;
cachedPlaces = (NSMutableSet *)CFSetCreateMutable(kCFAllocatorDefault,
0,
&callbacks);
That makes a non-retaining set. Note that you still need to remove the objects from the set when they are released, otherwise you will have stale pointers in your set that will cause you to crash on a deref. So in the objects you are adding to the set you need a dealloc something like this:
- (void)dealloc {
[cachedPlaces removeObject:self];
[super dealloc];
}
This is only really suitable for a purely in memory cache of extant references, if you need to also move stuff to and from the disk then CoreData basically takes care of all of this for you.
You could use NSMutableSet as cache and rely on the fact that any object it contains with a retain count of 1 is only owned by the cache. Thus any object with a retain count of 1 should be removed, this is easily done:
NSPredicate* predicate = [NSPredicate predicateWithFormat:#"retainCount > 1"];
[cachedPlaces filterUsingPredicate:predicate];
Do this on a timer, or whenever a a place is added and/or removed if that is not too often. You could also make the predicate a static to avoid generating anew instance every time.
Use Core Data if you can deploy to iPhoneOS 3.0 or greater, or use SQLite for iPhoneOS 2.x. Either way you'll be able to use a database to store your data, and you'll be able to do queries to get fresh data sets.
As of iOS 4.0, the proper way to do this is to use an NSCache. It can automatically purge objects when the system sends a low-memory warning. You can also set limits on the cache size.
NSCache Class Reference
This question is old, but I recently came across a similar issue. I believe using NSHashTable can fit the requirements of this situation.
NSHashTable works better than NSCache or NSSet because it can hold weak references to your instances, so that once all references are dropped the instance is automatically removed from the NSHashTable thanks to ARC. This works as a kind of 'Just-in-Time' caching method, only retaining objects held elsewhere by strong references.
Considering that you have multiple parts of the application that could be adding references, using the NSHashTable as the Flyweight Pool of the Flyweight Pattern could be useful. The second part of the Flyweight pattern requires a factory, the factory would be responsible for checking for the instance in the pool, adding it to the pool if it's not found, then returning the pooled instance.

Use autorelease before adding objects to a collection?

I have been looking through the questions asked on StackOverflow, but there are so many about memory management in Objective-C that I couldn't find the answer I was looking for.
The question is if it is ok (and recommnded) to call autorelease before adding a newly created object to a collection (like NSMutableArray)? Or should I release it explicitly after adding it. (I know NSMutableArray willl retain the object)
This illustrates my question:
Scenario A (autorelease):
- (void) add {
// array is an instance of NSMutableArray
MyClass *obj = [[[MyClass alloc] init] autorelease];
[array addObject:obj];
}
Scenario B (explicit release):
- (void) add {
// array is an instance of NSMutableArray
MyClass *obj = [[MyClass alloc] init];
[array addObject:obj];
[obj release];
}
I assume both are correct, but I am not sure, and I sure don't know what the preffered way is.
Can the Objective-C gurus shed some light on this?
IMHO, which way is 'right' is a matter of preference. I don't disagree with the responders who advocate not using autorelease, but my preference is to use autorelease unless there is an overwhelmingly compelling reason not to. I'll list my reasons and you can decide whether or not their appropriate to your style of programming.
As Chuck pointed out, there is a semi-urban legend that there's some kind of overhead to using autorelease pools. This could not be further from the truth, and this comes from countless hours spent using Shark.app to squeeze the last bit of performance out of code. Trying to optimize for this is deep in to "premature optimization" territory. If, and only if, Shark.app gives you hard data that this might be a problem should you even consider looking in to it.
As others pointed out, an autoreleased object is "released at some later point". This means they linger around, taking up memory, until that "later point" rolls around. For "most" cases, this is at the bottom of an event processing pass before the run loop sleeps until the next event (timer, user clicking something, etc).
Occasionally, though, you will need to get rid of those temporary objects sooner, rather than later. For example, you need to process a huge, multi-megabyte file, or tens of thousands of rows from a database. When this happens, you'll need to place a NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; at a well chosen point, followed by a [pool release]; at the bottom. This almost always happens in some kind of "loop batch processing", so it's usually at the start and bottom of some critical loop. Again, this should be evidence based, not hunch based. Instrument.app's ObjectAlloc is what you use to find these trouble spots.
The main reason why I prefer autorelease to release, though, is that it is much easier to write leak-free programs. In short, if you choose to go the release route, you need to guarantee that release is eventually sent to obj, under all circumstances. While this seems like it might be simple, it is actually surprisingly hard to do in practice. Take your example, for instance:
// array is an instance of NSMutableArray
MyClass *obj = [[MyClass alloc] init];
[array addObject:obj];
// Assume a few more lines of work....
[obj release];
Now imagine that for some reason, something, somewhere, subtly violates your assumption that array is mutable, maybe as the result of using some method to process the results, and the returned array containing the processed results was created as a NSArray. When you send addObject: to that immutable NSArray, an exception will be thrown, and you will never send obj its release message. Or maybe something goes wrong somewhere between when obj was allocd and the required call to release, like you check some condition and return() immediately by mistake because it slipped your mind that that call to release later on must take place.
You have just leaked an object. And probably signed yourself up to several days of trying to find out where and why it is your leaking it. From experience, you will spend many hours looking at that code above, convinced that it could not possibly be the source of the leak because you very clearly send obj a release. Then, after several days, you will experience what can only be described as a religious epiphany as you are enlightened to the cause of the problem.
Consider the autorelease case:
// array is an instance of NSMutableArray
MyClass *obj = [[[MyClass alloc] init] autorelease];
[array addObject:obj];
// Assume a few more lines of work....
Now, it no longer matters what happens because it's virtually impossible to leak obj accidentally, even under extremely unusual or exceptional corner cases.
Both are correct and will work as you're expecting them to.
I personally prefer to use the latter method, but only because I like to be explicit about when objects get released. By autoreleasing the object, all we're doing is saying "this object will get released at some arbitrary point in the future." That means you can put the autoreleased object into the array, destroy the array, and the object might (probably) still exist.
With the latter method, the object would get destroyed immediately with the array (providing that nothing else has come along and retained it in the meantime). If I'm in a memory-constrained environment (say, the iPhone) where I need to be careful about how much memory I'm using, I'll use the latter method just so I don't have so many objects lingering in an NSAutoreleasePool somewhere. If memory usage isn't a big concern for you (and it usually isn't for me, either), then either method is totally acceptable.
They are both correct but B may be preferred because it has no overhead at all. Autorelease causes the autorelease pool to take charge of the object. This has a very slight overhead which, of course, gets multiplied by the number of objects involved.
So with one object A and B are more or less the same but definitely don't use A in scenarios with lots of objects to add to the array.
In different situations autoreleasing may delay and accumulate the freeing of many objects at the end of the thread. This may be sub-optimal. Take care that anyway autoreleasing happens a lot without explicit intervention. For example many getters are implemented this way:
return [[myObject retain] autorelease];
so whenever you call the getter you add an object to the autorelease pool.
You can send the autorelease message at any point, because it isn't acted on until the application's message loop repeats (i.e. until all your methods have finished executing in response to user input).
http://macdevcenter.com/pub/a/mac/2001/07/27/cocoa.html?page=last&x-showcontent=text
You have alloc'ed the object, then it's your job to release it at some point. Both code snippets work merely the same, correct way, with the autorelease way being the potentionally slower counterpart.
Personally speaking, I prefer the autorelease way, since it's just easier to type and almost never is a bottleneck.
They're both OK. Some people will tell you to avoid autorelease because of "overhead" or some such thing, but the truth is, there is practically no overhead. Go ahead and benchmark it and try to find the "overhead." The only reason you'd avoid it is in a memory-starved situation like on the iPhone. On OS X, you have practically unlimited memory, so it isn't going to make much of a difference. Just use whichever is most convenient for you.
I prefer A (autoreleasing) for brevity and "safety", as johne calls it. It simplifies my code, and I've never run into problems with it.
That is, until today: I had a problem with autoreleasing a block before adding it to an array. See my stackoverflow question:
[myArray addObject:[[objcBlock copy] autorelease]] crashes on dealloc'ing the array (Update: Turns out the problem was elsewhere in my code, but still, there was a subtle difference in behavior with autorelease…)

iphone memory management

I have a method that returns a NSMutableArray:
//implementation of class Students
-(NSMutableArray *)listOfStudents {
NSMutableArray *students = [[NSMutableArray alloc] init];
//add objects to students and other operations here
return students;
}
The problem here is, when and where do I release the object students? If it was an instance variable, I would add a [students release] in the dealloc method, but it's not. The class Students allocated the object, so it owns the new NSMutableArray and it must release it, right?
Since I can't release it before return it, the only option I see here is... return it as:
return [students autorelease];
But it doesn't feel right to use autorelease objects on the iPhone. This method will be called many times... and I would like to release the memory as soon as possible. Also, the autorelease pool is in the main function and it looks like it will take a while to clean the mess.
How would you do it?
I tend to avoid using autorelease wherever I can within my iPhone applications, but there are some cases where it doesn't hurt you that much. If the array that you're generating via this method will be retained for a reasonably long duration, then you won't be sacrificing any performance or memory usage by returning it as an autoreleased result.
However, if you will be using and discarding the returned object quite frequently, you may wish to do something different. I have a naming convention with my methods that if something is prefixed by "generate", like generateStudentsArray, it returns an object that is owned by the caller and must be manually released (like with copy). This helps to avoid using autoreleased objects, but it adds another thing to remember when doing memory management.
Additionally, because memory allocation / deallocation is costly (especially on the iPhone), you may wish to avoid the frequent allocations and deallocations within a method called quite a lot and instead recycle the mutable array by creating it ahead of time and passing it into the method, which only adds to the array's contents.
You're right, autorelease is the standard idiom to use in a situation like this.
UIKit actually creates an autorelease pool at the start of each event cycle and releases it at the end, so your autoreleased objects will get cleared up then; they won't be hanging around forever.
If you had a loop that was calling this method many times within a single event cycle, you might want to create your own autorelease pool inside that loop so that these objects get released at the end of each iteration, rather than building up loads of objects to be released at the end of the current event cycle.
But unless you're doing something like that, or you are encountering another specific out-of-memory situation, UIKit's standard autorelease pools should handle it fine.