关于脏NIF函数需要知道的一些知识
- 默认情况下,虚拟机给你N个脏CPU调度器,其中N是正常调度器的数量。正常调度器的数量默认为系统上配置的逻辑处理器的数量。
- 不指定脏调度器数量的情况下,脏调度器的数量等同于普通调度器的数量,既
-smp +S 1
等同于-smp +S 1 +SDcpu 1
,此时系统中存在一个普通调度器线程和一个脏调度器线程。 - 脏NIF函数不会影响到普通函数,是不是可以认为完全不需要拆分脏调度函数呢。同样做下实验:
static ERL_NIF_TERM loop_sleep(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]){
Sleep(2000);
int n = 0;
ErlNifPid pid;
enif_get_int(env, argv[0], &n);
enif_get_local_pid(env,argv[1],&pid);
printf("loop:%d\n",n);
if(n > 0){
ERL_NIF_TERM new_argv[] = {enif_make_int(env, n-1),argv[1]};
return loop_sleep(env, argc, new_argv);
// return enif_schedule_nif(env, "loop_sleep", ERL_NIF_DIRTY_JOB_CPU_BOUND, loop_sleep, 2, new_argv);
}else{
return atom_ok;
}
}
([email protected])34> nif_server2:mfa(nif_random2,test,[{nif_server:p()}]).
ok
([email protected])35> loop:10
loop:9
loop:8
nif_server3:mfa(nif_random2,test,[{nif_server:p()}]).
ok
([email protected])36> loop:7
loop:10
loop:6
loop:9
loop:5
loop:8
loop:4
loop:7
loop:3
loop:6
loop:2
loop:5
loop:1
loop:4
loop:0
loop:3
loop:2
loop:1
loop:0
将return loop_sleep(env, argc, new_argv);
注释掉,换成return enif_schedule_nif(env, "loop_sleep", ERL_NIF_DIRTY_JOB_CPU_BOUND, loop_sleep, 2, new_argv);
:
([email protected])38> nif_server2:mfa(nif_random2,test,[{nif_server:p()}]).
ok
([email protected])39> loop:10
loop:9
loop:8
nif_server3:mfa(nif_random2,test,[{nif_server:p()}]).
ok
([email protected])40> loop:7
loop:6
loop:5
loop:4
loop:3
loop:2
loop:1
loop:0
loop:10
loop:9
loop:8
loop:7
loop:6
loop:5
loop:4
loop:3
loop:2
loop:1
loop:0
脏调度器同样必须完整处理完一个NIF函数才会处理下一个NIF函数,所以更长时间的脏NIF函数明显会占用脏调度器更长时间,影响到别的脏NIF函数的使用,是否要将脏NIF函数也进行切割操作,取决于具体的业务情况。或许事实上可以认为,脏NIF函数没有执行时间敏感性,不在乎等待时间有多久。
另外从上面可以得到的一个信息是,脏NIF函数消耗的时间切片貌似很大?执行完一个脏NIF函数后立即切换到另一个进程执行别的脏NIF函数。