Throttle CPU usage on background thread

好久不见. 提交于 2019-12-30 07:59:08

问题


I have a CPU intensive task and I want it to use less CPU and take up more time.

I'm loading a massive amount of SCNNodes to a scene at start-up. It takes up a lot of memory, and I'd like it to work on it at a safe rate instead of lagging up my system or potentially crashing it.

Here's the code I'm using to load the nodes.

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");
    });
});

Here are the statistics:


回答1:


It might not be the best way to do this, but have you looked at prepareobject:?

Creating the NSObjects themselves shouldn't be that much of a problem, but preparing the geometry and adding it to the scene probably is. Bu deffering this step to a secondary thread you'll save some CPU and make the scene not stop until the node is ready to be added.

Once each node is ready, (completion handler) just add it to the scene. I won't throttle the loading, but it will at least handle it in a safer way for the rest of your app.

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];
        }
    }];

}



回答2:


Two ideas:

  1. Use NSOperationQueue, it has the method setThreadPriority: which can be used to throttle the load to some extend.

  2. Because you are dispatching on an asynchronous queue, maybe you can insert a sleep() function after processing every 100th Element or so. This should reduce the amount of work for the processor because the thread stalls for some percentage of the time, but it won't make your UI laggy, because its just a background queue.

Obviously this is going to sacrifice CPU load for execution time.




回答3:


It looks like you're not doing anything to limit the number of simultaneous operations. Doing this is probably going to be more effective than trying to throttle CPU usage as CPU usage throttling is a vague concept by comparison.

To limit the number of concurrent operations, you can do one of the following:

  1. Make a custom dispatch_queue using dispatch_queue_create("com.myApp.loadQueue", DISPATCH_QUEUE_SERIAL). DISPATCH_QUEUE_SERIAL prevents blocks in the queue from running concurrently.

  2. As @JoJoe mentioned in their answer, use an NSOperationQueue. I'd suggest using setConcurrentOperationCount: rather than setThreadPriority: to limit the number of concurrent operations. If you don't want to bother with setting up your own NSOperation subclass you can use NSBlockOperation.



来源:https://stackoverflow.com/questions/29705842/throttle-cpu-usage-on-background-thread

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!