mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-06 15:17:01 +02:00
MINOR: cpu-topo: add a CPU policy setting to the global section
We'll need to let the user decide what's best for their workload, and in order to do this we'll have to provide tunable options. For that, we're introducing struct ha_cpu_policy which contains a name, a description and a function pointer. The purpose will be to use that function pointer to choose the best CPUs to use and now to set the number of threads and thread-groups, that will be called during the thread setup phase. The only supported policy for now is "none" which doesn't set/touch anything (i.e. all available CPUs are used).
This commit is contained in:
parent
9a8e8af11a
commit
156430ceb6
@ -49,4 +49,19 @@ struct ha_cpu_cluster {
|
||||
uint nb_cpu; /* total CPUs */
|
||||
};
|
||||
|
||||
/* Description of a CPU selection policy. For now it only associates an option
|
||||
* name with a callback function that is supposed to adjust the global.nbthread
|
||||
* and global.nbtgroups based on the policy, the topology, and the constraints
|
||||
* on the number of threads which must be between tmin and tmax included, and
|
||||
* the number of thread groups which must be between gmin and gmax included.
|
||||
* The callback also takes the policy number (cpu_policy) and a pointer to a
|
||||
* string to write an error to in case of failure (in which case ret must be
|
||||
* < 0 and the caller will fre the location). More settings might come later.
|
||||
*/
|
||||
struct ha_cpu_policy {
|
||||
const char *name; /* option name in the configuration */
|
||||
const char *desc; /* short description for help messages */
|
||||
int (*fct)(int policy, int tmin, int tmax, int gmin, int gmax, char **err);
|
||||
};
|
||||
|
||||
#endif /* _HAPROXY_CPU_TOPO_T_H */
|
||||
|
@ -37,6 +37,11 @@ void cpu_compose_clusters(void);
|
||||
/* apply remaining topology-based cpu set restrictions */
|
||||
void cpu_refine_cpusets(void);
|
||||
|
||||
/* apply the chosen CPU policy. Returns < 0 on failure with a message in *err
|
||||
* that must be freed by the caller if non-null.
|
||||
*/
|
||||
int cpu_apply_policy(int tmin, int tmax, int gmin, int gmax, char **err);
|
||||
|
||||
/* Detects CPUs that are bound to the current process. Returns the number of
|
||||
* CPUs detected or 0 if the detection failed.
|
||||
*/
|
||||
|
@ -46,6 +46,15 @@ struct cpu_set_cfg {
|
||||
struct hap_cpuset drop_threads;
|
||||
} cpu_set_cfg;
|
||||
|
||||
/* CPU policy choice */
|
||||
static int cpu_policy = 0;
|
||||
|
||||
/* list of CPU policies for "cpu-policy". The default one is the first one. */
|
||||
static struct ha_cpu_policy ha_cpu_policy[] = {
|
||||
{ .name = "none", .desc = "use all available CPUs", .fct = NULL },
|
||||
{ 0 } /* end */
|
||||
};
|
||||
|
||||
/* Detects CPUs that are online on the system. It may rely on FS access (e.g.
|
||||
* /sys on Linux). Returns the number of CPUs detected or 0 if the detection
|
||||
* failed.
|
||||
@ -872,6 +881,29 @@ void cpu_refine_cpusets(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* apply the chosen CPU policy if no cpu-map was forced. Returns < 0 on failure
|
||||
* with a message in *err that must be freed by the caller if non-null.
|
||||
*/
|
||||
int cpu_apply_policy(int tmin, int tmax, int gmin, int gmax, char **err)
|
||||
{
|
||||
*err = NULL;
|
||||
|
||||
if (cpu_map_configured()) {
|
||||
/* nothing to do */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ha_cpu_policy[cpu_policy].fct) {
|
||||
/* nothing to do */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ha_cpu_policy[cpu_policy].fct(cpu_policy, tmin, tmax, gmin, gmax, err) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* CPU topology detection below, OS-specific */
|
||||
|
||||
#if defined(__linux__)
|
||||
@ -1330,6 +1362,36 @@ static int cfg_parse_cpu_set(char **args, int section_type, struct proxy *curpx,
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Parse the "cpu-policy" global directive, which takes the name of one of the
|
||||
* ha_cpu_policy[] names, and sets the associated index in cpu_policy.
|
||||
*/
|
||||
static int cfg_parse_cpu_policy(char **args, int section_type, struct proxy *curpx,
|
||||
const struct proxy *defpx, const char *file, int line,
|
||||
char **err)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (too_many_args(1, args, err, NULL))
|
||||
return -1;
|
||||
|
||||
for (i = 0; ha_cpu_policy[i].name; i++) {
|
||||
if (strcmp(args[1], ha_cpu_policy[i].name) == 0) {
|
||||
cpu_policy = i;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
memprintf(err, "'%s' passed an unknown CPU policy '%s'. Supported values are:", args[0], args[1]);
|
||||
for (i = 0; ha_cpu_policy[i].name; i++) {
|
||||
memprintf(err, "%s%s '%s' (%s)%s", *err,
|
||||
(i > 0 && ha_cpu_policy[i+1].name) ? "" : " and",
|
||||
ha_cpu_policy[i].name,
|
||||
ha_cpu_policy[i].desc,
|
||||
(ha_cpu_policy[i+1].name) ? "," : ".\n");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Allocates everything needed to store CPU topology at boot.
|
||||
* Returns non-zero on success, zero on failure.
|
||||
*/
|
||||
@ -1403,6 +1465,7 @@ REGISTER_POST_DEINIT(cpu_topo_deinit);
|
||||
|
||||
/* config keyword parsers */
|
||||
static struct cfg_kw_list cfg_kws = {ILH, {
|
||||
{ CFG_GLOBAL, "cpu-policy", cfg_parse_cpu_policy, 0 },
|
||||
{ CFG_GLOBAL, "cpu-set", cfg_parse_cpu_set, 0 },
|
||||
{ 0, NULL, NULL }
|
||||
}};
|
||||
|
@ -1549,6 +1549,7 @@ void thread_detect_count(void)
|
||||
int grp_max __maybe_unused;
|
||||
int cpus_avail __maybe_unused;
|
||||
int cpu __maybe_unused;
|
||||
char *err __maybe_unused;
|
||||
|
||||
thr_min = 1; thr_max = MAX_THREADS;
|
||||
grp_min = 1; grp_max = MAX_TGROUPS;
|
||||
@ -1614,6 +1615,13 @@ void thread_detect_count(void)
|
||||
* on the same cluster _capacity_ up to thr_max.
|
||||
*/
|
||||
|
||||
if (cpu_apply_policy(thr_min, thr_max, grp_min, grp_max, &err) < 0) {
|
||||
if (err)
|
||||
ha_warning("cpu-policy: %s\n", err);
|
||||
ha_free(&err);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Let's implement here the automatic binding to the first available
|
||||
* NUMA node when thread count is not set, taskset is not used and
|
||||
* no cpu-map directive is present.
|
||||
|
Loading…
Reference in New Issue
Block a user