为什么更新CALayer会导致CPU使用率(通过其他进程)增加60-70%? [英] Why updating CALayer causes increase of CPU usage (by other processes) by 60-70%?

查看:71
本文介绍了为什么更新CALayer会导致CPU使用率(通过其他进程)增加60-70%?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当许多 CALayers 呈现界面时,我正在使用 IOS 应用程序。我注意到图形更新期间, CPU 由其他进程(实际上不是应用程序)加载。我开始禁用界面部件的更新,直到只有一个 CALayer 被更新( 50-60 Hz ),但是所有其他层(数百个)都静态地更新了也显示。因此,仅此ONE层的更新将占用其他进程 60-70%的CPU 负载。禁用此唯一层的更新时,不会加载 CPU

I am witing IOS app when interface is presented by many CALayers. Once I noticed that CPU is loaded by other processes (not app actually) during graphics updates. I began to disabled updating of interface parts and went to the moment when only ONE CALayer was updated (at 50-60 Hz), but all other layers (hundreds) were statically displayed too. So updating of only this ONE layer costs 60-70% of CPU load by other processes. When disable update of this only layer, CPU is not loaded.

任何人都可以说这是怎么回事吗?

Can anyone say what is going on here??

[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];

// update layer which is sublayer of self.view.layer
self.headingCircularScaleLayer.transform = CATransform3DMakeRotation(DegToRad(-newHeadingAngle_deg), 0, 0, 1);

[self.view.layer setNeedsLayout];

[CATransaction commit];

此处 headingCircularScaleLayer 是CALayer,其内容设置为某些图像

Here headingCircularScaleLayer is CALayer which contents is set to some Image

注意_1:(通过添加多个层并更新它们来测试CPU负载)

NOTE_1: (test of CPU load by adding many layers and updating them)

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}

-(void) viewDidAppear:(BOOL)animated {

    [self createAndSetupLayers];

    CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateLayers)];
    [displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];

    self.startTime = [[NSDate date] timeIntervalSince1970];
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


-(void) createAndSetupLayers {

    NSMutableArray<CALayer*>* newLayersArray = [[NSMutableArray alloc] init];

    long numOfRows = 28;
    long numOfCols = 21;
    long numOfLayers = numOfRows * numOfCols;

    CGFloat cellWidth = self.view.bounds.size.width / numOfCols;
    CGFloat cellHeight = self.view.bounds.size.height / numOfRows;

    CGFloat layerWidth = cellWidth * 0.9;
    CGFloat layerHeight = cellHeight * 0.9;

    long currRow = 0;
    long currCol = 0;

    for (long i = 0; i < numOfLayers; i++)
    {
        currRow = i / numOfCols;
        currCol = i % numOfCols;

        CALayer* newLayer = [[CALayer alloc] init];

        newLayer.bounds = CGRectMake(0.0, 0.0, layerWidth, layerHeight);
        newLayer.anchorPoint = CGPointMake(0.5, 0.5);
        newLayer.position = CGPointMake((currCol + 0.5) * cellWidth, (currRow + 0.5) * cellHeight);
        newLayer.backgroundColor = [UIColor greenColor].CGColor;
        //newLayer.opacity = 0.5;

        //NSDictionary *newActions = @{ @"transform": [NSNull null] };
        //newLayer.actions = newActions;
        newLayer.actions = @{ @"contents": [NSNull null], @"position": [NSNull null],
                           @"frame": [NSNull null], @"opacity": [NSNull null],
                           @"bounds": [NSNull null], @"affineTransform": [NSNull null],
                           @"sublayerTransform": [NSNull null], @"transform": [NSNull null],
                           @"zPosition": [NSNull null], @"anchorPoint": [NSNull null],
                           @"cornerRadius": [NSNull null], @"sublayers": [NSNull null],
                           @"onLayout": [NSNull null], };


        CALayer* newColorLayer = [[CALayer alloc] init];
        newColorLayer.bounds = CGRectMake(0.0, 0.0, layerWidth, layerHeight);
        newColorLayer.anchorPoint = CGPointMake(0.5, 0.5);
        newColorLayer.position = CGPointMake(0.5 * layerWidth, 0.5 * layerHeight);
        newColorLayer.opacity = 0.5;
        newColorLayer.opaque = YES;
        newColorLayer.backgroundColor = [UIColor redColor].CGColor;

        //[newLayer addSublayer:newColorLayer];
        [self.view.layer addSublayer:newLayer];
        [newLayersArray addObject:newLayer];
    }

    self.layersArray = newLayersArray;
}

-(void) updateLayers {
    double currTime = [[NSDate date] timeIntervalSince1970] - self.startTime;

    double currLayerAngle = 0.5 * currTime;

    NSLog(@"%.2f  %.2f", currTime, currLayerAngle);

    //[CATransaction begin];
    //[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
    //[CATransaction setAnimationDuration:0.0];

    for (CALayer *currLayer in self.layersArray)
    {
        currLayer.transform = CATransform3DMakeRotation(currLayerAngle, 0, 0, 1);
    }

    //[CATransaction commit];
}

@end


推荐答案

如以上评论所述,设置 kCATransactionDisableActions 仅会影响当前交易。您可能在其他地方有启动隐式动画的代码。尝试将图层操作明确设置为null。创建图层时,您只需一次。在这种情况下,您不需要进行显式事务。

As said in the comments above, setting kCATransactionDisableActions will only affect the current transaction. You might have code in other places that starts implicit animations. Try explicitly setting the layer actions to null. You only need to do this once, when the layer is created. In this case you don't need to do explicit transactions.

layer.actions = @{ @"contents": [NSNull null], @"position": [NSNull null],
                   @"frame": [NSNull null], @"opacity": [NSNull null],
                   @"bounds": [NSNull null], @"affineTransform": [NSNull null],
                   @"sublayerTransform": [NSNull null], @"transform": [NSNull null],
                   @"zPosition": [NSNull null], @"anchorPoint": [NSNull null],
                   @"cornerRadius": [NSNull null], @"sublayers": [NSNull null],
                   @"onLayout": [NSNull null], };

这篇关于为什么更新CALayer会导致CPU使用率(通过其他进程)增加60-70%?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆