仅在第一次执行时性能缓慢

Posted

技术标签:

【中文标题】仅在第一次执行时性能缓慢【英文标题】:Slow performance on first exectuation only 【发布时间】:2014-03-21 07:25:51 【问题描述】:

我设置了一个基本计时器,用于记录完成我的自定义动画所需的时间。

- (void) performAnimationOfFrameAtIndex:(NSNumber*)indexNum

int index = indexNum.intValue;

BOOL completedSequece = index >= [self.frames count];
if (completedSequece) 
    BOOL repeatsRemaining = self.currentCycleCount < self.cyclesRepeatsValue;
    if (repeatsRemaining) 
        self.currentCycleCount ++;
        index = kFirstFrame;
    
    else 
        self.methodEnd = [NSDate date];
        [self logDurationToComplete];
        return;
    


UIImageView *imgIn;
UIImageView *imgOut;

if (index % 2 == 0) 
    imgIn = self.animationImageViewOne;
    imgOut = self.animationImageViewTwo;

else 
    imgIn = self.animationImageViewTwo;
    imgOut = self.animationImageViewOne;


imgIn.image = self.frames[index];
[self.view sendSubviewToBack:self.imgOut];

double speed = (index < self.frames.count * 0.5) ? self.inspirationDuration : self.expirationDuration;

[self performSelector:@selector(performAnimationOfFrameAtIndex:) withObject:[NSNumber numberWithInt:index + 1] afterDelay:speed];

我已将其设置为 1.0 秒

为什么第一次运行需要 1.2 -> 1.6 秒,而以下需要 1.0 秒。

如果将其设置为 2 秒,则第一次运行需要 2.2 -> 2.6 秒...

如果设置为 3 秒,则第一次运行需要 3.0 秒,所以

时间探查器表明

imgIn.image = self.frames[index];

消耗 100% 的时间,我尝试将 imgIn.image 设置为属性并在 viewDidLoad 中设置,但第一次运行延迟没有任何变化。

所有图片都已在 viewDidLoad 中预加载。

模拟器或设备上没有区别,方法调用开始使用IBAction

感谢您的任何想法...

【问题讨论】:

【参考方案1】:
[self performSelector: withObject: afterDelay:]

假设您已将延迟值设为 1 秒。上述函数使用了延迟触发事件的概念,这意味着对该函数的调用将在 1 秒后添加到执行 runLoop(Queue) 中。当它被添加到 runLoop(Queue) 中时,可能有机会(根据您的代码)队列中可能已经有一些其他函数调用。只有当队列项从前面移除并且当前前面的函数是你的函数时,它才有机会执行。

当您第一次执行某个操作时,可能某些函数已添加到队列中,因此您执行此函数时会有延迟。

【讨论】:

我在按下按钮时调用了这个方法,尝试使用执行选择器 / 和直接调用以零延迟调用。如果我注释掉 imgIn.image = self.frames[index];它第一次运行没有延迟,所以它必须是这个,但不知道如何克服这个..没有黑客方法..【参考方案2】:

经过更多的思考和研究,我发现了这个不错的bit of info

我将此添加到我的 viewDidLoad 中,问题解决了。

- (void) preloadImages

dispatch_queue_t downloadQueue = dispatch_queue_create("imagePreLoader", NULL);
dispatch_async(downloadQueue, ^

    for (int i = 0; i < kNumberBreathingImages; i++) 
        UIImage * img = [self.frames objectAtIndex:i];
        CGImageRef ref = img.CGImage;
        size_t width = CGImageGetWidth(ref);
        size_t height = CGImageGetHeight(ref);
        CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
        CGContextRef context = CGBitmapContextCreate(NULL, width, height, 8, width * 4, space, kCGBitmapAlphaInfoMask & kCGImageAlphaPremultipliedFirst);
        CGColorSpaceRelease(space);
        CGContextDrawImage(context, CGRectMake(0, 0, width, height), ref);
        CGContextRelease(context);
    

    dispatch_async(dispatch_get_main_queue(), ^
        self.breathButton.enabled = YES;
    );
);

【讨论】:

以上是关于仅在第一次执行时性能缓慢的主要内容,如果未能解决你的问题,请参考以下文章

为啥模拟的 Parallel 函数在第一次运行时执行缓慢但随后加速?

Apollo Server 解析大数据时性能缓慢

boost::thread interrupt() 仅在第一次执行中断点时引发异常?

仅在第一次测试时执行数据迁移

Django模板仅在for循环中第一次出现匹配时执行

仅在元素完全加载时执行一次的函数