Cocos2dx中线程优先级
Cocos2dx中线程优先级问题
不论是ios还是android,遇到耗时的任务都要另起线程处理,否则程序不能及时用户的反馈。游戏中如果一圈循环不能在1/frameRate(帧率是30则1/30)秒内完成,就会有掉帧,游戏卡顿。比如,游戏中要解析一个动画json配置,需要60ms,这如果在主线程中搞就掉帧了,那么另再开个线程解析json,解析完了再通知主线程如何?这是可以的,但是考虑一种极端情况,线程切换到json解析线程,直到json解析完成后才切换到主线程,这不是一样掉帧吗!所以理想情况是让json解析线程的优先级低于主线程,在主线程空闲时才进行json解析,这就与控制线程的优先级了,那么cocos2dx中可以设置线程的优先级吗?请看下文。
1.创建线程方式:
创建线程采用c++11中thread库,但是c++11中thread没有指定线程优先级或cpu亲和度(affinity)的相关方法(比如sched_setaffinity、 SetThreadAffinityMask、 pthread_attr_setschedpolicy)。需要用到pthread库中函数(目前用的是pthread_setschedparam),才可能控制线程优先级。
2. 线程优先级:
类unix系统中线程优先级调度策略常用的有SCHED_OTHER、SCHED_FIFO、SCHED_RR,其他的还有SCHED_BATCH、SCHED_BATCH、SCHED_IDLE。可以参考sched_setscheduler(2) - Linux man page。
SCHED_OTHER:新创建的线程默认情况下是此调度方式,主线程也是此调度方式,此调度方式没有线程优先级,在所有线程都是SCHED_OTHER调度方式时,由操作系统进行公平调度。
SCHED_FIFO和SCHED_RR: 有优先级的调度,有优先级高的线程,操作系统运行运行优先级高的线程。当既有SCHED_OTHER也有SCHED_FIFO(或SCHED_RR)时,SCHED_FIFO(或SCHED_RR)总是先于SCHED_OTHER运行。
SCHED_FIFO和SCHED_RR区别是:若线程优先级一样,则SCHED_FIFO按照FIFO的顺序运行,后进入的线程要等前面线程运行完或放弃cpu才能执行。SCHED_RR会进行时间片轮转,时间片到了,切换执行线程。
SCHED_OTHER优点是不用处理线程的实时(有高优先级线程来立即切换线程)切换,cpu利用率会比SCHED_FIFO和SCHED_RR高。
可以参考linux进程调度方法(SCHED_OTHER,SCHED_FIFO,SCHED_RR)
SCHED_OTHER,可以设置线程的cpu占用率(不是优先级),所以下面不同优先级(占用率)打印的log数不同。http://www.cnblogs.com/zengkefu/p/5560918.html
3.结论:
若不改变主线程的默认调度规则SCHED_OTHER,则通过pthread_setschedparm设置线程优先级无效果,也就是说不能保证其他的线程一定不影响主线程的执行效率。若将主线程的调度规则改为SCHED_FIFO(或SCHED_RR),创建的线程也设置调度规则为SCHED_FIFO并设置低优先级,可以保证主线程有更高cpu占用率。
在AppDelegate::applicationDidFinishLaunching中加入如下代码改变主线程调度方式,游戏可以正常运行,副作用暂时没有发现。
4.测试数据
打印的线程优先级优先级最大值最小值都是47到15,不是传说中的1到99。SCHED_OTHER max is 47, min is 15。SCHED_FIFO max is 47, min is 15。SCHED_RR max is 47, min is 15。每次测试开2个线程(线程1和线程2),分别设置调度方式和优先级,红字是令人费解的地方。
mac下mac模拟器
|
调度方式 |
优先级 |
Log打印次数 |
线程1 |
SCHED_OTHER |
46 |
16374 |
线程2 |
SCHED_OTHER |
16 |
311 |
线程1 |
SCHED_OTHER |
16 |
579 |
线程2 |
SCHED_OTHER |
46 |
7856 |
线程1 |
SCHED_OTHER |
30 |
1400 |
线程2 |
SCHED_OTHER |
31 |
8082 |
线程1 |
SCHED_OTHER |
31 |
8628 |
线程2 |
SCHED_OTHER |
30 |
1864 |
线程1 |
SCHED_RR |
16 |
1099 |
线程2 |
SCHED_OTHER |
46 |
12784 |
Mac下ios模拟器
|
调度方式 |
优先级 |
Log打印次数 |
线程1 |
SCHED_OTHER |
46 |
16799 |
线程2 |
SCHED_OTHER |
16 |
238 |
线程1 |
SCHED_OTHER |
16 |
3982 |
线程2 |
SCHED_OTHER |
46 |
103177 |
线程1 |
SCHED_OTHER |
30 |
2147 |
线程2 |
SCHED_OTHER |
31 |
21478 |
线程1 |
SCHED_RR |
16 |
1674 |
线程2 |
SCHED_OTHER |
46 |
16096 |
iphone 5s:
|
调度方式 |
优先级 |
Log打印次数 |
线程1 |
SCHED_OTHER |
46 |
463/ 1465/1553 |
线程2 |
SCHED_OTHER |
16 |
1781/1726/1568 |
线程1 |
SCHED_OTHER |
16 |
1030 |
线程2 |
SCHED_OTHER |
46 |
1284 |
线程1 |
SCHED_OTHER |
30 |
372 |
线程2 |
SCHED_OTHER |
31 |
2005 |
线程1 |
SCHED_RR |
16 |
52262 |
线程2 |
SCHED_OTHER |
46 |
1161 |
线程1 |
SCHED_RR |
46 |
13055 |
线程2 |
SCHED_RR |
16 |
1145 |
线程1 |
SCHED_RR |
46 |
19858 |
线程2 |
SCHED_RR |
45 |
2046 |
Mac下 app
|
调度方式 |
优先级 |
Log打印次数 |
线程1 |
SCHED_OTHER |
46 |
13099 |
线程2 |
SCHED_OTHER |
16 |
59311 |
线程1 |
SCHED_OTHER |
16 |
45864 |
线程2 |
SCHED_OTHER |
46 |
3598 |
线程1 |
SCHED_OTHER |
30 |
7512 |
线程2 |
SCHED_OTHER |
31 |
4561 |
线程1 |
SCHED_RR |
16 |
57981 |
线程2 |
SCHED_OTHER |
46 |
5909 |
线程1 |
SCHED_RR |
46 |
58960 |
线程2 |
SCHED_RR |
45 |
5494 |
测试代码mac app:
Cocos2dx测试代码: