MINOR: activity: add configuration and CLI support for "profiling.tasks"
This is a new global setting which enables or disables CPU profiling per task. For now it only sets/resets the variable based on the global option "profiling.tasks" and supports showing it as well as setting it from the CLI using "show profiling" and "set profiling". The option will be used by a future commit. It was done in a way which should ease future addition of profiling options.
This commit is contained in:
parent
baba82fe70
commit
75c62c2793
@ -619,6 +619,7 @@ The following keywords are supported in the "global" section :
|
||||
- nosplice
|
||||
- nogetaddrinfo
|
||||
- noreuseport
|
||||
- profiling.tasks
|
||||
- spread-checks
|
||||
- server-state-base
|
||||
- server-state-file
|
||||
@ -1434,6 +1435,16 @@ noreuseport
|
||||
Disables the use of SO_REUSEPORT - see socket(7). It is equivalent to the
|
||||
command line argument "-dR".
|
||||
|
||||
profiling.tasks { on | off }
|
||||
Enables ('on') or disables ('off') per-task CPU profiling. CPU profiling per
|
||||
task can be very convenient to report where the time is spent and which
|
||||
requests have what effect on which other request. It is not enabled by
|
||||
default as it may consume a little bit extra CPU. This requires a system
|
||||
supporting the clock_gettime(2) syscall with clock identifiers
|
||||
CLOCK_MONOTONIC and CLOCK_THREAD_CPUTIME_ID, otherwise the reported time will
|
||||
be zero. This option may be changed at run time using "set profiling" on the
|
||||
CLI.
|
||||
|
||||
spread-checks <0..50, in percent>
|
||||
Sometimes it is desirable to avoid sending agent and health checks to
|
||||
servers at exact intervals, for instance when many logical servers are
|
||||
|
@ -1649,6 +1649,11 @@ set maxconn global <maxconn>
|
||||
delayed until the threshold is reached. A value of zero restores the initial
|
||||
setting.
|
||||
|
||||
set profiling { tasks } { on | off }
|
||||
Enables or disables CPU profiling for the indicated subsystem. This is
|
||||
equivalent to setting or clearing the "profiling" settings in the "global"
|
||||
section of the configuration file. Please also see "show profiling".
|
||||
|
||||
set rate-limit connections global <value>
|
||||
Change the process-wide connection rate limit, which is set by the global
|
||||
'maxconnrate' setting. A value of zero disables the limitation. This limit
|
||||
@ -2045,6 +2050,10 @@ show pools
|
||||
as the SIGQUIT when running in foreground except that it does not flush
|
||||
the pools.
|
||||
|
||||
show profiling
|
||||
Dumps the current profiling settings, one per line, as well as the command
|
||||
needed to change them.
|
||||
|
||||
show servers state [<backend>]
|
||||
Dump the state of the servers found in the running configuration. A backend
|
||||
name or identifier may be provided to limit the output to this backend only.
|
||||
|
@ -28,6 +28,10 @@
|
||||
#include <types/activity.h>
|
||||
#include <proto/freq_ctr.h>
|
||||
|
||||
/* bit fields for "profiling" */
|
||||
#define HA_PROF_TASKS 0x00000001 /* enable per-task CPU profiling */
|
||||
|
||||
extern unsigned int profiling;
|
||||
extern struct activity activity[MAX_THREADS];
|
||||
|
||||
|
||||
|
100
src/activity.c
100
src/activity.c
@ -10,11 +10,19 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <common/cfgparse.h>
|
||||
#include <common/config.h>
|
||||
#include <common/standard.h>
|
||||
#include <common/hathreads.h>
|
||||
#include <types/activity.h>
|
||||
#include <proto/channel.h>
|
||||
#include <proto/cli.h>
|
||||
#include <proto/freq_ctr.h>
|
||||
#include <proto/stream_interface.h>
|
||||
|
||||
|
||||
/* bit field of profiling options. Beware, may be modified at runtime! */
|
||||
unsigned int profiling;
|
||||
|
||||
/* One struct per thread containing all collected measurements */
|
||||
struct activity activity[MAX_THREADS] __attribute__((aligned(64))) = { };
|
||||
@ -29,3 +37,95 @@ void report_stolen_time(uint64_t stolen)
|
||||
update_freq_ctr(&activity[tid].cpust_1s, stolen);
|
||||
update_freq_ctr_period(&activity[tid].cpust_15s, 15000, stolen);
|
||||
}
|
||||
|
||||
/* config parser for global "profiling.tasks", accepts "on" or "off" */
|
||||
static int cfg_parse_prof_tasks(char **args, int section_type, struct proxy *curpx,
|
||||
struct proxy *defpx, const char *file, int line,
|
||||
char **err)
|
||||
{
|
||||
if (too_many_args(1, args, err, NULL))
|
||||
return -1;
|
||||
|
||||
if (strcmp(args[1], "on") == 0)
|
||||
profiling |= HA_PROF_TASKS;
|
||||
else if (strcmp(args[1], "off") == 0)
|
||||
profiling &= ~HA_PROF_TASKS;
|
||||
else {
|
||||
memprintf(err, "'%s' expects either 'on' or 'off' but got '%s'.", args[0], args[1]);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* parse a "set profiling" command. It always returns 1. */
|
||||
static int cli_parse_set_profiling(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
unsigned int bit = 0;
|
||||
|
||||
if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
|
||||
return 1;
|
||||
|
||||
if (strcmp(args[2], "tasks") == 0)
|
||||
bit = HA_PROF_TASKS;
|
||||
else {
|
||||
appctx->ctx.cli.severity = LOG_ERR;
|
||||
appctx->ctx.cli.msg = "Expects 'tasks'.\n";
|
||||
appctx->st0 = CLI_ST_PRINT;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (strcmp(args[3], "on") == 0)
|
||||
HA_ATOMIC_OR(&profiling, bit);
|
||||
else if (strcmp(args[3], "off") == 0)
|
||||
HA_ATOMIC_AND(&profiling, ~bit);
|
||||
else {
|
||||
appctx->ctx.cli.severity = LOG_ERR;
|
||||
appctx->ctx.cli.msg = "Expects either 'on' or 'off'.\n";
|
||||
appctx->st0 = CLI_ST_PRINT;
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* This function dumps all profiling settings. It returns 0 if the output
|
||||
* buffer is full and it needs to be called again, otherwise non-zero.
|
||||
*/
|
||||
static int cli_io_handler_show_profiling(struct appctx *appctx)
|
||||
{
|
||||
struct stream_interface *si = appctx->owner;
|
||||
|
||||
if (unlikely(si_ic(si)->flags & (CF_WRITE_ERROR|CF_SHUTW)))
|
||||
return 1;
|
||||
|
||||
chunk_reset(&trash);
|
||||
|
||||
chunk_printf(&trash, "Per-task CPU profiling : %s # set profiling tasks {on|off}\n",
|
||||
(profiling & HA_PROF_TASKS) ? "on" : "off");
|
||||
|
||||
if (ci_putchk(si_ic(si), &trash) == -1) {
|
||||
/* failed, try again */
|
||||
si_rx_room_blk(si);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* config keyword parsers */
|
||||
static struct cfg_kw_list cfg_kws = {ILH, {
|
||||
{ CFG_GLOBAL, "profiling.tasks", cfg_parse_prof_tasks },
|
||||
{ 0, NULL, NULL }
|
||||
}};
|
||||
|
||||
/* register cli keywords */
|
||||
static struct cli_kw_list cli_kws = {{ },{
|
||||
{ { "show", "profiling", NULL }, "show profiling : show CPU profiling options", NULL, cli_io_handler_show_profiling, NULL },
|
||||
{ { "set", "profiling", NULL }, "set profiling : enable/disable CPU profiling", cli_parse_set_profiling, NULL },
|
||||
{{},}
|
||||
}};
|
||||
|
||||
__attribute__((constructor))
|
||||
static void __activity_init(void)
|
||||
{
|
||||
cfg_register_keywords(&cfg_kws);
|
||||
cli_register_kw(&cli_kws);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user