0

I am developing a game for iOS with Obj-C and Apple's SpriteKit framework. My primary testing device is an iPad2 (model #MC773X/A running iOS8.1). My game runs smoothly on this device except for a single "stutter" around 60-120s in. At this time the app lags for around 150-300ms / 10-20 frames.

I have tested the same game app on an iPhone6+ (model #MGAJ2X/A running iOS8.4) which doesn't seem to have this problem.

I originally thought it had something to do with my game apps resource management, and then later maybe the debugging link itself... so I created the following testing app. It is simply a blank screen, that logs dt's above 20ms. It has an option to log to the screen (using SKLabelNodes) for testing without a debugging link.

This simple testing app shows the same stutter on the iPad2 without fail at around the 60s mark (built in debug/release, with/without debugging). The iPhone 6+ doesn't show the stuttering behaviour.

Starting with a new SpriteKit game template for iOS (I am using Xcode 6.4 but I saw the same bug with an earlier version - Xcode 6.something):

In GameViewController.m:

//scene.scaleMode = SKSceneScaleModeAspectFill;
scene.scaleMode = SKSceneScaleModeResizeFill;

Replace GameScene.m with:

#import "GameScene.h"

#define LOG_TO_SCREEN

static int dtLogCounter = 1;
#ifdef LOG_TO_SCREEN
static const int dtLogLabelNum = 10; //5;
#endif

@interface GameScene ()
@property (nonatomic) CFTimeInterval prevTime;
@property (nonatomic) CFTimeInterval startTime;
#ifdef LOG_TO_SCREEN
@property (strong, nonatomic) SKLabelNode *timeLabel;
@property (strong, nonatomic) NSArray *dtLogLabels;
#endif
@end

@implementation GameScene

-(void)didMoveToView:(SKView *)view
{
#ifdef LOG_TO_SCREEN
CGFloat screenWidth = view.bounds.size.width;

_timeLabel = [SKLabelNode labelNodeWithFontNamed:@"Courier"];
_timeLabel.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeRight;
_timeLabel.fontSize = 16.0;
_timeLabel.position = CGPointMake(screenWidth - 7.0, 28.0);
[self addChild:_timeLabel];

NSMutableArray *dtLogLabels = [NSMutableArray arrayWithCapacity:dtLogLabelNum];
for (int i = 0; i < dtLogLabelNum; i++)
{
    SKLabelNode *dtLogLabel = [SKLabelNode labelNodeWithFontNamed:@"Courier"];
    dtLogLabel.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeRight;
    dtLogLabel.fontSize = 16.0;
    dtLogLabel.position = CGPointMake(screenWidth - 7.0, 100.0 + 25*i);
    [self addChild:dtLogLabel];
    [dtLogLabels addObject:dtLogLabel];
}
_dtLogLabels = [NSArray arrayWithArray:dtLogLabels];
#endif

    _prevTime = _startTime = CACurrentMediaTime();
}

-(void)update:(CFTimeInterval)currentTime
{
    CFTimeInterval dt = currentTime - _prevTime;
    _prevTime = currentTime;

    CFTimeInterval gameTime = currentTime - _startTime;

#ifdef LOG_TO_SCREEN
    _timeLabel.text = [NSString stringWithFormat:@"t:%.1f(c)", gameTime];
#endif

    if (dt > 20e-3)
    {
        NSString *logStr = [NSString stringWithFormat:@"#%d:%.1f:%.0f  ", dtLogCounter++, gameTime, dt*1000];
#ifdef LOG_TO_SCREEN
        for (int i = dtLogLabelNum-1; i > 0; i--)
        {
            SKLabelNode *dtLogLabel = [_dtLogLabels objectAtIndex:i];
            SKLabelNode *prevLabel = [_dtLogLabels objectAtIndex:i-1];
            dtLogLabel.text = prevLabel.text;
        }
        SKLabelNode *firstDtLogLabel = [_dtLogLabels objectAtIndex:0];
        firstDtLogLabel.text = logStr;
#else
        NSLog(@"%@", logStr);
#endif
    }
}

@end

I am getting comfortable with using the time profiler instrument but in this case I don't think it is particularly helpful. It shows no activity for the duration of the stutter. (image1) (Unfortunately I'm a brand new poster so can't inline images)

It seems like it is a system process happening at this time which is causing the app to stutter. The activity monitor instrument shows a peak at this time but I don't really know how to interpret the data / nothing obvious stands out. (image2)

The system usage instrument shows no activity in the I/O activity track.

The file activity instrument doesn't seem to be available.

My question is: how should I approach debugging this issue? Which instrument could I use, and how?

Confirmation that others see this issue on this/other hardware would be appreciated as would suggestions to it's cause/resolution.

Thanks

O2easy
  • 1
  • 2
  • You can use the uploader and include a link to the image. You just can't display it inline, but other users can edit that for you. – jscs Aug 28 '15 at 01:52
  • @JoshCaswell thanks. I've edited in links to time profiler and activity monitor instruments screen clippings – O2easy Aug 28 '15 at 02:03

1 Answers1

0

If you haven't already, I suggest you read Apple's Analyzing CPU Usage in Your App. If that does not yield any positive results for you, peppering your code with NSLog statements can be another way to try to pinpoint the code section involved with this issue.

Do keep in mind that you are probably not seeing the stutter in the iPhone 6+ due to its faster CPU. The iPad 2 is somewhat dated and runs much slower. This itself is a small clue to your issue.

sangony
  • 11,636
  • 4
  • 39
  • 55