在后台线程上限制CPU使用率

时间:2015-04-17 17:31:16

标签: objective-c scenekit

我有一个CPU密集型任务,我希望它使用更少的CPU并占用更多时间。

我正在启动时向场景加载大量SCNNode。它占用了大量内存,我希望它以安全的速度工作,而不是滞后我的系统或可能会崩溃。

这是我用来加载节点的代码。

dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^(void){
    NSLog(@"Start Loading Level");
    SCNNode *cameraNode = [SCNNode node];
    cameraNode.camera = [SCNCamera camera];
    cameraNode.camera.zFar = 5000;
    cameraNode.position = SCNVector3Make(0, 3000, 0);
    cameraNode.rotation = SCNVector4Make(1, 0, 0, -M_PI_2);
    [scene.rootNode addChildNode:cameraNode];
    for (int i = 0; i < 100000; i++)
    {
        int side = 3000;
        SCNNode *node = [SCNNode node];
        node.geometry = [SCNBox boxWithWidth:1 height:1 length:1 chamferRadius:0];
        node.position = SCNVector3Make(arc4random_uniform(side) - side / 2.0,
                                       0,
                                       arc4random_uniform(side) - side / 2.0);
        [scene.rootNode addChildNode:node];
    }
    dispatch_async(dispatch_get_main_queue(), ^(void){
        NSLog(@"Finished");
    });
});

以下是统计数据:

Image Usage over Time Image Memory

3 个答案:

答案 0 :(得分:8)

这可能不是最好的方法,但是你看过prepareobject:吗?

创建NSObject本身不应该是一个问题,但准备几何并将其添加到场景可能是。将此步骤发布到辅助线程,您将保存一些CPU并使场景不会停止,直到节点准备好添加为止。

每个节点准备就绪后,(完成处理程序)只需将其添加到场景中即可。我不会限制加载,但它至少会以更安全的方式为你的应用程序处理它。

https://developer.apple.com/library/prerelease/ios/documentation/SceneKit/Reference/SCNSceneRenderer_Protocol/index.html#//apple_ref/occ/intfm/SCNSceneRenderer/prepareObjects:withCompletionHandler

-(void)prepareLevel{
    // Mutable Array to save the nodes
    NSMutableArray *nodes = [[NSMutableArray alloc] init];

    for (int i = 0; i < 100000; i++)
    {
        int side = 3000;
        SCNNode *node = [SCNNode node];
        node.geometry = [SCNBox boxWithWidth:1 height:1 
                                      length:1 chamferRadius:0];
        node.position = SCNVector3Make(arc4random_uniform(side) - side / 2.0,
                                       0,
                                       arc4random_uniform(side) - side / 2.0);

        [nodes addObject:node];
    }

    [mySCNView prepareObjects:nodes withCompletionHandler:^(BOOL success) {
        for(SCNNode*node in nodes){
            [scene.rootNode addChildNode:node];
        }
    }];

}

答案 1 :(得分:2)

两个想法:

  1. 使用NSOperationQueue,它有方法setThreadPriority:可用于在一定程度上限制负载。

  2. 因为您正在调度异步队列,所以您可以在处理每100个元素之后插入一个sleep()函数。这应该减少处理器的工作量,因为线程在一定比例的时间内停滞,但它不会使你的UI滞后,因为它只是一个后台队列。

  3. 显然,这会牺牲CPU负载的执行时间。

答案 2 :(得分:1)

看起来你没有做任何事情来限制同时操作的数量。这样做可能比尝试限制CPU使用率更有效,因为CPU使用量限制是一个模糊的概念。

要限制并发操作的数量,您可以执行以下操作之一:

  1. 使用dispatch_queue制作自定义dispatch_queue_create("com.myApp.loadQueue", DISPATCH_QUEUE_SERIAL)DISPATCH_QUEUE_SERIAL可防止队列中的块同时运行。

  2. 正如@JoJoe在回​​答中提到的那样,使用NSOperationQueue。我建议使用setConcurrentOperationCount:而不是setThreadPriority:来限制并发操作的数量。如果您不想打扰设置自己的NSOperation子类,可以使用NSBlockOperation