2

I just ran into a weird behaviour with NSOperation that I fixed but do not understand.

I subclassed NSOperation by following the documentation. When I use the main method below, the application will use 100% or more of the CPU time.

-(void)main 
{
    @try 
    {
        NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

        //Cycle forever until told to cancel
        while (![self isCancelled])
        {

        }

        [pool release];
    }
    @catch(...) 
    {
        // Do not rethrow exceptions.
    }

    //Finish executing
    [self completeOperation]; //Send notificatios using KVO
}

Conversely when I use the following main method, the application uses 3% of the CPU time.

-(void)main 
{
    @try 
    {
        NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

        //Create the initial delayed timers
        NSTimer *startUpTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerFireMethod:) userInfo:nil repeats:YES];

        NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
        [runLoop addTimer:startUpTimer forMode:NSRunLoopCommonModes];
        [runLoop run];

        //Cycle forever until told to cancel
        while (![self isCancelled])
        {

        }

        [pool release];
    }
    @catch(...) 
    {
        // Do not rethrow exceptions.
    }

    //Finish executing
    [self completeOperation]; //Send notificatios using KVO
}

This strange behaviour appears to be attributed to the timer. If the timer is asked to not repeat itself, the application uses 100% CPU time, but if the timer is asked to repeat itself, then the CPU usage is normal.

It appears that when nothing is running on the thread, the CPU usage is really high (I would assume it would be the opposite). Any suggestions on why this is the case?

Thanks.

David
  • 14,205
  • 20
  • 97
  • 144

2 Answers2

14

Cycling a while loop will take 100% of a single core of a CPU. This is what a loop does, regardless of being in a queue or not.

v01d
  • 1,576
  • 14
  • 19
  • I don't exactly agree. Both methods have while loops in them, but one uses more CPU time than the other. – David Jan 27 '11 at 03:32
  • 5
    Correct, the second while loop is not being executed because your run loop is instead. – v01d Jan 27 '11 at 03:33
  • Perhaps it has something to do with the timer interacting with the loop's execution. How do you think timers are implemented? Loops running in their own threads measuring elapsed clock cycles. – Marc W Jan 27 '11 at 03:35
  • 1
    Take a look at the documentation for NSRunLoop. The -(void)run method says this: "Puts the receiver into a permanent loop, during which time it processes data from all attached input sources." Basically the run loop is not exiting until you ask it to. That means the CPU is doing nothing until your timer fires. The while loop will not get executed until the run loop is exited. – v01d Jan 27 '11 at 03:38
  • 1
    Marc W: er, no, that’s not how timers are implemented, because that would be insane. When the run loop runs, it looks through its list of timers for the one with the lowest next fire time, and uses that as a timeout if it needs to sleep the thread. (You can see this in the CFLite source code: `__CFRunLoopGetNextTimerFireTSR()` in CFRunLoop.c finds the next fire time, then that’s used to specify the timeout for `WaitForMultipleObjects()`.) – Jens Ayton Jan 27 '11 at 07:47
  • 2
    v01d: Not just until it fires, but until it is invalidated (removed from the run loop). As long as it is valid, the run loop will keep running, and a repeating timer is valid until you explicitly invalidate it. – Peter Hosey Jan 27 '11 at 10:30
  • @v01d, you're absolutely right. The "while()" after the run loop never executes as long as the timer is running. Thanks for the clarification. – David Jan 27 '11 at 16:36
0

as of iPhone equivalent of Application.DoEvents();

add

        while (![self isCancelled])
        {


 [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:10]]
        }

and see how things go.

Community
  • 1
  • 1
Anonymous White
  • 2,149
  • 3
  • 20
  • 27