节流 CPU 在后台线程上的使用
Throttle CPU usage on background thread
我有一个 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");
});
});
以下是统计数据:
这可能不是最好的方法,但您看过 prepareobject:
了吗?
创建 NSObjects 本身应该不是什么大问题,但准备几何体并将其添加到场景中可能是大问题。如果将此步骤推迟到辅助线程,您将节省一些 CPU 并使场景在节点准备好添加之前不会停止。
每个节点准备就绪后,(完成处理程序)只需将其添加到场景中即可。我不会限制加载,但它至少会以更安全的方式处理您应用程序的其余部分。
-(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];
}
}];
}
两个想法:
使用 NSOperationQueue,它有方法 setThreadPriority: 可以用来在一定程度上限制负载。
因为你是在异步队列上调度,也许你可以在每处理第 100 个元素后插入一个 sleep() 函数。这应该会减少处理器的工作量,因为线程会在一定比例的时间内停止,但它不会使您的 UI 延迟,因为它只是一个后台队列。
显然这将牺牲 CPU 负载来换取执行时间。
您似乎没有采取任何措施来限制同时操作的数量。这样做可能比尝试限制 CPU 使用更有效,因为相比之下 CPU 使用限制是一个模糊的概念。
要限制并发操作的数量,您可以执行以下操作之一:
使用 dispatch_queue_create("com.myApp.loadQueue", DISPATCH_QUEUE_SERIAL)
自定义 dispatch_queue
。 DISPATCH_QUEUE_SERIAL
阻止队列中的块同时 运行。
正如@JoJoe 在他们的回答中提到的那样,使用 NSOperationQueue
。我建议使用 setConcurrentOperationCount:
而不是 setThreadPriority:
来限制并发操作的数量。如果您不想设置自己的 NSOperation
子类,您可以使用 NSBlockOperation
.
我有一个 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");
});
});
以下是统计数据:
这可能不是最好的方法,但您看过 prepareobject:
了吗?
创建 NSObjects 本身应该不是什么大问题,但准备几何体并将其添加到场景中可能是大问题。如果将此步骤推迟到辅助线程,您将节省一些 CPU 并使场景在节点准备好添加之前不会停止。
每个节点准备就绪后,(完成处理程序)只需将其添加到场景中即可。我不会限制加载,但它至少会以更安全的方式处理您应用程序的其余部分。
-(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];
}
}];
}
两个想法:
使用 NSOperationQueue,它有方法 setThreadPriority: 可以用来在一定程度上限制负载。
因为你是在异步队列上调度,也许你可以在每处理第 100 个元素后插入一个 sleep() 函数。这应该会减少处理器的工作量,因为线程会在一定比例的时间内停止,但它不会使您的 UI 延迟,因为它只是一个后台队列。
显然这将牺牲 CPU 负载来换取执行时间。
您似乎没有采取任何措施来限制同时操作的数量。这样做可能比尝试限制 CPU 使用更有效,因为相比之下 CPU 使用限制是一个模糊的概念。
要限制并发操作的数量,您可以执行以下操作之一:
使用
dispatch_queue_create("com.myApp.loadQueue", DISPATCH_QUEUE_SERIAL)
自定义dispatch_queue
。DISPATCH_QUEUE_SERIAL
阻止队列中的块同时 运行。正如@JoJoe 在他们的回答中提到的那样,使用
NSOperationQueue
。我建议使用setConcurrentOperationCount:
而不是setThreadPriority:
来限制并发操作的数量。如果您不想设置自己的NSOperation
子类,您可以使用NSBlockOperation
.