在使用Greenplum的过程中,发现CPU监控有大量的%ni的占比。
ni是指低优先级的用户模式,通过setpriority可以设置进程的优先级。数字越大,优先级越低。
TOP中CPU统计的分类解释如下:
2c. SUMMARY Area Fields
The summary area fields describing CPU statistics are abbreviated. They provide information about times spent in:
us = user mode
sy = system mode
ni = low priority user mode (nice)
id = idle task
wa = I/O waiting
hi = servicing IRQs
si = servicing soft IRQs
st = steal (time given to other DomU instances)
setpriority 用法如下:
NAME
getpriority, setpriority - get/set program scheduling priority
SYNOPSIS
#include <sys/time.h>
#include <sys/resource.h>
int getpriority(int which, int who);
int setpriority(int which, int who, int prio);
查看greenplum的源码,在src/backend/tcop/postgres.c中发现了setpriority的踪迹。
/*
* Change the priority of the current process to the specified level
* (bigger nice_level values correspond to lower priority).
*/
static bool renice_current_process(int nice_level)
{
#ifdef WIN32
elog(DEBUG2, "Renicing of processes on Windows currently not supported.");
return false;
#else
int prio_out = -1;
elog(DEBUG2, "Current nice level of the process: %d",
getpriority(PRIO_PROCESS, 0));
prio_out = setpriority(PRIO_PROCESS, 0, nice_level);
if (prio_out == -1)
{
switch (errno)
{
case EACCES:
elog(DEBUG1, "Could not change priority of the query process, errno: %d (%m).", errno);
break;
case ESRCH:
/* ignore this, the backend went away when we weren't looking */
break;
default:
elog(DEBUG1, "Could not change priority of the query process, errno: %d (%m).", errno);
}
return false;
}
elog(DEBUG2, "Reniced process to level %d", getpriority(PRIO_PROCESS, 0));
return true;
#endif
}
以上函数在exec_mpp_query时被调用:
/*
* exec_mpp_query
*
* Called in a qExec process to read and execute a query plan sent by
* cdbdisp_dispatchPlan().
*
* query_string -- optional query text (C string).
* serializedQuerytree[len] -- Query node or (NULL,0) if plan provided.
* serializedPlantree[len] -- PlannedStmt node, or (NULL,0) if query provided.
* serializedParms[len] -- optional parameters
* serializedSliceInfo[len] -- optional SliceTable
* localSlice -- slice table index
*
* Caller may supply either a Query (representing utility command) or
* a PlannedStmt (representing a planned DML command), but not both.
*/
static void
exec_mpp_query(const char *query_string,
const char * serializedQuerytree, int serializedQuerytreelen,
const char * serializedPlantree, int serializedPlantreelen,
const char * serializedParams, int serializedParamslen,
const char * serializedSliceInfo, int serializedSliceInfolen,
const char * seqServerHost, int seqServerPort,
int localSlice)
{
...
/* Downgrade segworker process priority */
if (gp_segworker_relative_priority != 0)
{
renice_current_process(PostmasterPriority + gp_segworker_relative_priority);
}
gp_segworker_relative_priority 是一个启动参数,默认是20:
{
{"gp_segworker_relative_priority", PGC_POSTMASTER, RESOURCES_MGM,
gettext_noop("Priority for the segworkers relative to the postmaster's priority."),
NULL,
GUC_NO_SHOW_ALL | GUC_NOT_IN_SAMPLE
},
&gp_segworker_relative_priority,
PRIO_MAX,
0, PRIO_MAX, NULL, NULL
},
...
src/include/cdb/cdbvars.h:#define PRIO_MAX 20
因此就能解释,为什么使用greenplum会发现大量的nice占比的CPU统计。