Is it more efficient to schedule a method to spawn enemies or use the update method of an Enemy cache? - objective-c

I am using Cocos2d for iPhone and I am wondering if it is more efficient to structure the logic of my code to spawn enemies using this method:
-(void) schedule:(SEL)selector interval:(ccTime)interval
or using the update in an EnemyCache class and verify each time if the time interval is met. Here is the code snippet that is called in the update method of the EnemyCache class (the relative time is an integer value that is updated by the GameScene at each update in the GameScene class - the GameScene update method call is scheduled with an interval of 1 second):
-(void) checkForPlayerCollisionsAndSpwanTime
{
int count = [elements count];
//CCLOG(#"count %i", count);
Element* element;
for(int i=0; i<count;i++){
element = [elements objectAtIndex:i];
NSAssert(element!=nil, #"Nil enemy");
if (element.visible)
{
[element justComeDown];
ShipEntity * ship = [[GameScene sharedGameScene]defaultShip];
CGRect rect = [ship boundingBox];
if (CGRectIntersectsRect([element boundingBox], rect)){
[element doWhatever];
element.visible=FALSE;
[element stopAllActions];
}
}
else{
if(element.spawnTime == relativeTime) {
[self addChild:element];
element.visible=TRUE;
}
}
}
}
The difference is that in this way at each update the checkForPlayerCollisionsAndSpwanTime method goes through the array of enemies. In the first way, via scheduling a selector to call a similar method, I could reduce the time spent by the CPU to look through the array and conditions.
I am not sure how costly is this call:
[self schedule:selector interval:interval repeat:kCCRepeatForever delay:0];
Looking through I see that calls this method (See below) but I wanted to ask in general what is your approach for this problem and whether I should keep using the EnemyCache update method or use the scheduleSelector methods.
-(void) scheduleSelector:(SEL)selector forTarget:(id)target interval:(ccTime)interval paused:(BOOL)paused repeat:(uint) repeat delay:(ccTime) delay
{
NSAssert( selector != nil, #"Argument selector must be non-nil");
NSAssert( target != nil, #"Argument target must be non-nil");
tHashSelectorEntry *element = NULL;
HASH_FIND_INT(hashForSelectors, &target, element);
if( ! element ) {
element = calloc( sizeof( *element ), 1 );
element->target = [target retain];
HASH_ADD_INT( hashForSelectors, target, element );
// Is this the 1st element ? Then set the pause level to all the selectors of this target
element->paused = paused;
} else
NSAssert( element->paused == paused, #"CCScheduler. Trying to schedule a selector with a pause value different than the target");
if( element->timers == nil )
element->timers = ccArrayNew(10);
else
{
for( unsigned int i=0; i< element->timers->num; i++ ) {
CCTimer *timer = element->timers->arr[i];
if( selector == timer->selector ) {
CCLOG(#"CCScheduler#scheduleSelector. Selector already scheduled. Updating interval from: %.4f to %.4f", timer->interval, interval);
timer->interval = interval;
return;
}
}
ccArrayEnsureExtraCapacity(element->timers, 1);
}
CCTimer *timer = [[CCTimer alloc] initWithTarget:target selector:selector interval:interval repeat:repeat delay:delay];
ccArrayAppendObject(element->timers, timer);
[timer release];
}

Do you have a performance problem in your app? If not, the answer is: it doesn't matter. If you do, did you measure it and did the issue come from the method in question? If not, the answer is: you're looking in the wrong place.
In other words: premature optimization is the root of all evil.
If you still want to know, there's just one way to find out: measure both variants of the code and pick the one that's faster. If the speed difference is minimal (which I suspect it will be), favor the version that's easier for you to work with. There's a different kind of performance you should consider: you, as a human being, reading, understanding, changing code. Code readability and maintainability is way more important than performance in almost all situations.
No one can (or will) look at this amount of code and conclude "Yes, A is definitely about 30-40% faster, use A". If you are concerned about the speed of the method, don't let anyone tell you which is faster. Measure it. It's the only way you can be sure.
The reason is this: programmer's are notorious about making assumptions about code performance. Many times they're wrong, because the language or hardware or understanding of the topic have made big leaps the last time they measured it. But more likely they're going to remember what they've learned because once they've asked a question just like yours, and someone else gave them an answer which they accepted as fact from then on.
But coming back to your specific example: it really doesn't matter. You're much, much, much, much, much more likely to run into performance issues due to rendering too many enemies than the code that determines when to spawn one. And then it really, really, really, really, really doesn't matter if that code is run in a scheduled selector or a scheduled update method that increases a counter every frame. This boils down to being a subjective coding style preference issue a lot more than it is a decision about performance.

Related

How can doing tasks in multiple threads be 100 times slower than doing sequentially on the main thread?

I have this other question of mine where I have asked about converting a code from sequential to parallel processing using Grand Central Dispatch.
I will copy the question text to makes things easy...
I have an array of NSNumbers that have to pass thru 20 tests. If one test fails than the array is invalid if all tests pass than the array is valid. I am trying to do it in a way that as soon as the first failure happens it stops doing the remaining tests. If a failure happens on the 3rd test then stop evaluating other tests.
Every individual test returns YES when it fails and NO when it is ok.
I am trying to convert the code I have that is serial processing, to parallel processing with grand central dispatch, but I cannot wrap my head around it.
This is what I have.
First the definition of the tests to be done. This array is used to run the tests.
#define TESTS #[ \
#"averageNotOK:", \
#"numbersOverRange:", \
#"numbersUnderRange:",\
#"numbersForbidden:", \
// ... etc etc
#"numbersNotOnCurve:"]
- (BOOL) numbersPassedAllTests:(NSArray *)numbers {
NSInteger count = [TESTS count];
for (int i=0; i<count; i++) {
NSString *aMethodName = TESTS[i];
SEL selector = NSSelectorFromString(aMethodName);
BOOL failed = NO;
NSMethodSignature *signature = [[self class] instanceMethodSignatureForSelector:selector];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setSelector:selector];
[invocation setTarget:self];
[invocation setArgument:&numbers atIndex:2];
[invocation invoke];
[invocation getReturnValue:&failed];
if (failed) {
return NO;
}
}
return YES;
}
This work perfectly but performs the tests sequentially.
After working on the code with the help of an user, I got this code using grand central dispatch:
- (BOOL) numbersPassedAllTests:(NSArray *)numbers {
volatile __block int32_t hasFailed = 0;
NSInteger count = [TESTS count];
__block NSArray *numb = [[NSArray alloc] initWithArray:numbers];
dispatch_apply(
count,
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0),
^(size_t index)
{
// do no computation if somebody else already failed
if(hasFailed) {
return;
}
SEL selector = NSSelectorFromString(TESTS[index]);
BOOL failed = NO;
NSMethodSignature *signature = [[self class] instanceMethodSignatureForSelector:selector];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setSelector:selector];
[invocation setTarget:self];
[invocation setArgument:&numb atIndex:2];
[invocation invoke];
[invocation getReturnValue:&failed];
if(failed)
OSAtomicIncrement32(&hasFailed);
});
return !hasFailed;
}
Activity Monitor shows what appears to be the cores being used with more intensity but this code is at least 100 times slower than the older one working sequentially!
How can that be?
If your methods that you're calling are simple, the overhead of creating all of these threads could offset any advantage gained by concurrency. As the Performing Loop Iterations Concurrently section of the Concurrency Programming Guide says:
You should make sure that your task code does a reasonable amount of work through each iteration. As with any block or function you dispatch to a queue, there is overhead to scheduling that code for execution. If each iteration of your loop performs only a small amount of work, the overhead of scheduling the code may outweigh the performance benefits you might achieve from dispatching it to a queue. If you find this is true during your testing, you can use striding to increase the amount of work performed during each loop iteration. With striding, you group together multiple iterations of your original loop into a single block and reduce the iteration count proportionately. For example, if you perform 100 iterations initially but decide to use a stride of 4, you now perform 4 loop iterations from each block and your iteration count is 25. For an example of how to implement striding, see “Improving on Loop Code.”
That link to Improving on Loop Code walks through a sample implementation of striding, whereby you balance the number of threads with the amount of work done by each. It will take some experimentation to find the right balance with your methods, so play around with different striding values until you achieve the best performance.
In my experiments with a CPU-bound process, I found that I achieved a huge gain when doing two threads, but it diminished after that point. It may vary based upon what is in your methods that you're calling.
By the way, what are these methods that you're calling doing? If you're doing anything that requires the main thread (e.g. UI updates), that will also skew the results. For the sake of comparison, I'd suggest you take your serial example and dispatch that to a background queue (as a single task), and see what sort of performance you get that way. This way you can differentiate between main vs. background queue related issues, and the too-many-threads overhead issue I discuss above.
Parallel computing only makes sense if you have enough tasks for each node to do. Otherwise, the extra overhead of setting up/managing the parallel nodes takes up more time than the problem itself.
Example of bad parallelization:
void function(){
for(int i = 0; i < 1000000; ++i){
for(int j = 0; j < 1000000; ++j){
ParallelAction{ //Turns the following code into a thread to be done concurrently.
print(i + ", " + j)
}
}
}
Problem: every print() statement has to be turned into a thread, where a worker node has to initialize, acquire the thread, finish, and find a new thread.
Essentially, you've got 1 000 000 * 1 000 000 threads waiting for a node to work on them.
How to make the above better:
void function(){
for(int i = 0; i < 1000000; ++i){
ParallelAction{ //Turns the following code into a thread to be done concurrently.
for(int j = 0; j < 1000000; ++j){
print(i + ", " + j)
}
}
}
This way, every node can start up, do a sizeable amount of work (print 1 000 000 things), finish up, and find a new job.
http://en.wikipedia.org/wiki/Granularity
The above link talks about granularity, the amount breaking up of a problem that you do.

Objective-c pendulum modelling memory issues

I am trying to implement a modelling class for a Physics project with finite difference methods for simulating a simple pendulum. I want to be able to make this class as generic as possible so I can do whatever I want with the values on each iteration of the method. For this reason I have given my methods callback blocks which can also be used to stop the method if we want to.
For example my Euler method loop looks like so:
for (NSInteger i = 0; i < n; i++) {
if (callBack) {
if(!callBack(NO, currentTheta, currentThetaDot, currentT, (CGFloat)i/n)) break;
}
currentTheta += self.dt*f_single_theta(currentThetaDot);
currentThetaDot += self.dt*f_single_thetaDot(currentTheta, currentThetaDot, gamma);
currentT += self.dt;
}
And in the callBack block I run the code
^BOOL (BOOL complete, double theta, double thetaDot, CGFloat timeElapsed, CGFloat percentComplete){
eulerT = [eulerT stringByAppendingFormat:#"%.8f\n",timeElapsed];
eulerTheta = [eulerTheta stringByAppendingFormat:#"%.8f\n",theta];
if ((currentThetaDot*currentThetaDot + cos(currentTheta)) > 0.5) {
return 0; // stops running if total E > 0.5
}
return 1;
}];
Where eulerT and eulerTheta are strings which I later save to a file. This callback method quickly results in a massive build up of memory, even for n of order 10,000 I end up with about 1Gb of RAM usage. As soon as I comment out calling the callBack block this drops right off. Is there anyway I can keep this nice functionality without the massive memory problems?
Many people who are new to Objective C do not realize the difference between [NSArray array] and [[NSArray alloc] init]. In the days before ARC, the difference was much more obvious now. Both create a new object, but the former allocates the object, assigns it to the current NSAutoreleasePool, and leaves it with a retain count of 0 while the latter allocates it and leaves it with a retain count of 1.
Objects that are assigned to an NSAutoreleasePool do not get deallocated immediately when the retain count reaches 0. Instead, they get deallocated when the OS gets time to. Generally this can be assumed to be when control returns to the current run loop, but it can also be when drain is called on the NSAutoreleasePool.
With ARC, the difference is less obvious, but still significant. Many, if not most, of the objects your allocate are assigned to an autorelease pool. This means that you don't get them back just because you're done using them. That leads to the memory usage spiking in tight loops, such as what you posted. The solution is to explicitly drain your autorelease pool, like this:
for (NSInteger i = 0; i < n; i++) {
if (callBack) {
#autoreleasepool {
if(!callBack(NO, currentTheta, currentThetaDot, currentT, (CGFloat)i/n))
break;
}
}
currentTheta += self.dt*f_single_theta(currentThetaDot);
currentThetaDot += self.dt*f_single_thetaDot(currentTheta, currentThetaDot, gamma);
currentT += self.dt;
}
You should wrap the inside of your loop in #autoreleasepool{} to clean up temporary objects.

Programmatically selecting a segment in UISegmentedControl based on title of that segment

I have a UISegmentedControl with several segments, each with a different "title". I want to be able to read in a NSString, and programmatically select the segment whose title matches that string. Say I start with something like:
NSString *stringToMatch = #"foo";
UISegmentedControl *seg = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:#"foo",#"bar",#"baz", nil]];
I want to do something like:
[seg selectSegmentWithTitle:stringToMatch];
But since there is no method called selectSegmentWithTitle, this doesn't work. Is anyone aware of a method that would be similar to this though?
I've also thought of looping over all the titles in seg, similar to this:
int i = 0;
for (UISegment *thisSeg in [seg allSegmentsInOrder])
{
if ([thisSeg.title isEqualToString:stringToMatch])
{
[seg setSelectedSegmentIndex:i];
break;
}
i++;
}
but to my knowledge there is no such thing as UISegment, nor is there a method allSegmentsInOrder. Again, does anyone know of any changes I could make to get this to work?
Thirdly, I could probably subclass UISegmentedControl to somehow add the methods I want it to have. I hate subclassing like that though, cause I'd have to go and re-declare all my segments and other inconvenient things like that. But it may be the only way to go...
Perhaps the way to do this is totally different from the three ideas I listed above. I'm open to whatever.
So while I was typing this question up, I kept searching and realized that my second method from OP is pretty close. I figured I should still post what I came up with, in case someone else is looks for something like this in the future.
for (int i = 0; i < [seg numberOfSegments]; i++)
{
if ([[seg titleForSegmentAtIndex:i] isEqualToString:stringToMatch])
{
[seg setSelectedSegmentIndex:i];
break;
}
//else {Do Nothing - these are not the droi, err, segment we are looking for}
}
if ([seg selectedSegmentIndex] == -1)
{
NSLog(#"Error - segment with title %# not found in seg",stringToMatch);
NSLog(#"Go back and fix your code, you forgot something");
// prob should do other stuff here to let the user know something went wrong
}
This still feels a little hacky, and is probably against some best practice guide somewhere, but if there's a finite list of titles and you can be certain stringToMatch will always be on that list, I'm thinking it should be fine.

Can I create an array prior to running a method?

int indexOfArray = 0;
-(void)pushNumber:(double)number{
if(self.numArray == NULL)
self.numArray = [NSMutableArray array];
indexOfArray = self.numArray.count;
[self.numArray insertObject:[NSNumber numberWithDouble:number] atIndex:(indexOfArray)];
indexOfArray--;
}
This is currently what part of my code looks like for a push method I am doing. The way I want to set it up is to push the number to the end of the array because that will allow me to pop the first number I pushed in using lastObject. I have experience in Java, but I have been making my way to Objective-C on my own, hence I am not sure if what I am doing is right. What I do know right now is that ever time this method runs indexOfArray will reset its count, and I don't want that. I want to be able to initialize the array before the method so I can have a constant size to start with which I can then decrement each time this method is called.
To be clear, this is for a calculator app I am making in my free time. I want to be able to reset the indexOfArray every the user presses a number after an operator, when the user presses clear, or when the user presses the = button.
If you're looking for an equivalent of a constructor in Java, override -init. Example:
- (id)init
{
self = [super init]
if (!self) {
return nil;
}
self.numArray = [NSMutableArray array];
return self;
}
However, as others have said, if your class is just a stack, it might be easier just to use an NSMutableArray, as it has methods for stack-like access.
Also, if int indexOfArray = 0; is really defined next to a method as it looks, you've got a global variable not an instance (/member) variable, which you might think you're declaring.
(if this stuff is new to you, I recommend reading Apple's Cocoa Core Competencies and Programming With Objective-C articles)

EXC_BAD_ACCESS when simply casting a pointer in Obj-C

Frequent visitor but first post here on StackOverflow, I'm hoping that you guys might be able to help me out with this. I'm fairly new to Obj-C and XCode, and I'm faced with this really... weird... problem. Googling hasn't turned up anything whatsoever. Basically, I get an EXC_BAD_ACCESS signal on a line that doesn't do any dereferencing or anything like that that I can see. Wondering if you guys have any idea where to look for this. I've found a work around, but no idea why this works... The line the broken version barfs out on is the line:
LevelEntity *le = entity;
where I get my bad access signal.
Here goes:
THIS VERSION WORKS
NSArray *contacts = [self.body getContacts];
for (PhysicsContact *contact in contacts)
{
PhysicsBody *otherBody;
if (contact.bodyA == self.body)
{
otherBody = contact.bodyB;
}
if (contact.bodyB == self.body)
{
otherBody = contact.bodyA;
}
id entity = [otherBody userData];
if (entity != nil)
{
LevelEntity *le = entity;
CGPoint point = [contact contactPointOnBody:otherBody];
}
}
THIS VERSION DOESNT WORK
NSArray *contacts = [self.body getContacts];
for (NSUInteger i = 0; i < [contacts count]; i++)
{
PhysicsContact *contact = [contacts objectAtIndex:i];
PhysicsBody *otherBody;
if (contact.bodyA == self.body)
{
otherBody = contact.bodyB;
}
if (contact.bodyB == self.body)
{
otherBody = contact.bodyA;
}
id entity = [otherBody userData];
if (entity != nil)
{
LevelEntity *le = entity;
CGPoint point = [contact contactPointOnBody:otherBody];
}
}
Here, the only difference between the two examples is the way I enumerate through my array. In the first version (which works) I use for (... in ...), where as in the second I use for (...; ...; ...). As far as I can see, these should be the same.
This is seriously weirding me out. Anyone have any similar experience or idea whats going on here? Would be really great :)
Cheers,
Alex
First, if you have a crash, you have a backtrace. Always provide the backtrace with your question (it'll be in the debugger and can be copy/pasted).
As Vojito implied, the most common cause of crashes like these is related to the over-releasing of objects.
In your case, for(;;) and for(... in ...) are not actually exactly the same. The latter is very likely causing the objects within the array to be retained for the duration of iteration or autoreleased upon retrieval (I say "very likely" because I didn't test it -- but it would explain the behavior).
In your code, you are modifying your object graph during iteration with statements like otherBody = contact.bodyB. If any one of those statements happens to cause one of the items in the array being iterated to be released out from under the array, you would see a crash. Similarly, if the modification of the object graph causes either contact.bodyA or contact.bodyB to become a dangling reference, you would see a crash.
All just an educated guess. Post the backtrace and, as Vojito suggested, run under the Allocation instrument in Instruments with zombie detection enabled.
Stack variables, including object references, will not automatically initialize to nil/0/NULL. Try setting otherBody to nil in its initializer:
PhysicsBody *otherBody = nil;
If the debugger is saying that the le assignment is where the exception occurs, it actually may be the statement above it, i.e. [otherBody userData]. Without initializing it, otherBody is a garbage value.