Small ddsperf enhancements
* Change default behaviour with no arguments to print help text; "ddsperf sanity" now gives the behaviour that it used to give when run with no arguments; * Include context switch rate in output; * Allow suffixing frequencies and sizes with standard units (so "size 1kB" is now allowed); * Add missing option to help text, extend help text with some additional informationr. Signed-off-by: Erik Boasson <eb@ilities.com>
This commit is contained in:
parent
ca04ac48de
commit
40ba6b207f
4 changed files with 122 additions and 34 deletions
|
@ -212,7 +212,7 @@ This example shows a few things:
|
||||||
the address or the interface name). Proper use of multiple network interfaces simultaneously will
|
the address or the interface name). Proper use of multiple network interfaces simultaneously will
|
||||||
come, but is not there yet.
|
come, but is not there yet.
|
||||||
* ``AllowMulticast`` configures the circumstances under which multicast will be used. If the
|
* ``AllowMulticast`` configures the circumstances under which multicast will be used. If the
|
||||||
selected interface doesn't support it, it obviously wonn't be used (``false``); but if it does
|
selected interface doesn't support it, it obviously won't be used (``false``); but if it does
|
||||||
support it, the type of the network adapter determines the default value. For a wired network, it
|
support it, the type of the network adapter determines the default value. For a wired network, it
|
||||||
will use multicast for initial discovery as well as for data when there are multiple peers that
|
will use multicast for initial discovery as well as for data when there are multiple peers that
|
||||||
the data needs to go to (``true``); but on a WiFi network it will use it only for initial
|
the data needs to go to (``true``); but on a WiFi network it will use it only for initial
|
||||||
|
@ -225,13 +225,13 @@ This example shows a few things:
|
||||||
the size of the UDP payload), and the size of the fragments into which very large samples get
|
the size of the UDP payload), and the size of the fragments into which very large samples get
|
||||||
split (which needs to be "a bit" less). Large values such as these typically improve performance
|
split (which needs to be "a bit" less). Large values such as these typically improve performance
|
||||||
over the (current) default values.
|
over the (current) default values.
|
||||||
* ``WhcHigh`` determines when the sender will wait for acknolwedgements from the readers because it
|
* ``WhcHigh`` determines when the sender will wait for acknowledgements from the readers because it
|
||||||
has buffered too much unacknowledged data. There is some auto-tuning, the (current) default value
|
has buffered too much unacknowledged data. There is some auto-tuning, the (current) default value
|
||||||
is a bit small to get really high throughput.
|
is a bit small to get really high throughput.
|
||||||
|
|
||||||
The configurator tool ``cycloneddsconf`` can help in discovering the settings, as can the config
|
The configurator tool ``cycloneddsconf`` can help in discovering the settings, as can the config
|
||||||
dump. Background information on configuring Cyclone DDS can be
|
dump. Background information on configuring Cyclone DDS can be
|
||||||
found [here](https://docs/manual/config.rst).
|
found [here](docs/manual/config.rst).
|
||||||
|
|
||||||
# Trademarks
|
# Trademarks
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ bool print_cputime (const struct CPUStats *s, const char *prefix, bool print_hos
|
||||||
{
|
{
|
||||||
int n = (int) strlen (s->hostname);
|
int n = (int) strlen (s->hostname);
|
||||||
if (n > 100) n = 100;
|
if (n > 100) n = 100;
|
||||||
pos += (size_t) snprintf (line + pos, sizeof (line) - pos, " @%*.*s:%"PRId32, n, n, s->hostname, s->pid);
|
pos += (size_t) snprintf (line + pos, sizeof (line) - pos, " @%*.*s:%"PRIu32, n, n, s->hostname, s->pid);
|
||||||
}
|
}
|
||||||
if (s->maxrss > 1048576)
|
if (s->maxrss > 1048576)
|
||||||
pos += (size_t) snprintf (line + pos, sizeof (line) - pos, " rss:%.1fMB", s->maxrss / 1048576.0);
|
pos += (size_t) snprintf (line + pos, sizeof (line) - pos, " rss:%.1fMB", s->maxrss / 1048576.0);
|
||||||
|
@ -58,6 +58,7 @@ bool print_cputime (const struct CPUStats *s, const char *prefix, bool print_hos
|
||||||
else {
|
else {
|
||||||
/* non-sensical value -- presumably maxrss is not available */
|
/* non-sensical value -- presumably maxrss is not available */
|
||||||
}
|
}
|
||||||
|
pos += (size_t) snprintf (line + pos, sizeof (line) - pos, " vcsw:%"PRIu32" ivcsw:%"PRIu32, s->vcsw, s->ivcsw);
|
||||||
const size_t init_pos = pos;
|
const size_t init_pos = pos;
|
||||||
for (uint32_t i = 0; i < s->cpu._length; i++)
|
for (uint32_t i = 0; i < s->cpu._length; i++)
|
||||||
{
|
{
|
||||||
|
@ -81,6 +82,8 @@ struct record_cputime_state_thr {
|
||||||
struct record_cputime_state {
|
struct record_cputime_state {
|
||||||
bool supported;
|
bool supported;
|
||||||
dds_time_t tprev;
|
dds_time_t tprev;
|
||||||
|
uint32_t vcswprev;
|
||||||
|
uint32_t ivcswprev;
|
||||||
size_t nthreads;
|
size_t nthreads;
|
||||||
struct record_cputime_state_thr *threads;
|
struct record_cputime_state_thr *threads;
|
||||||
dds_entity_t wr;
|
dds_entity_t wr;
|
||||||
|
@ -118,13 +121,20 @@ bool record_cputime (struct record_cputime_state *state, const char *prefix, dds
|
||||||
|
|
||||||
ddsrt_rusage_t usage;
|
ddsrt_rusage_t usage;
|
||||||
if (ddsrt_getrusage (DDSRT_RUSAGE_SELF, &usage) < 0)
|
if (ddsrt_getrusage (DDSRT_RUSAGE_SELF, &usage) < 0)
|
||||||
|
{
|
||||||
usage.maxrss = 0;
|
usage.maxrss = 0;
|
||||||
|
usage.nvcsw = usage.nivcsw = 0;
|
||||||
|
}
|
||||||
double max = 0;
|
double max = 0;
|
||||||
double du_skip = 0.0, ds_skip = 0.0;
|
double du_skip = 0.0, ds_skip = 0.0;
|
||||||
const double dt = (double) (tnow - state->tprev) / 1e9;
|
const double dt = (double) (tnow - state->tprev) / 1e9;
|
||||||
bool some_above = false;
|
bool some_above = false;
|
||||||
|
|
||||||
state->s.maxrss = (double) usage.maxrss;
|
state->s.maxrss = (double) usage.maxrss;
|
||||||
|
state->s.vcsw = (uint32_t) ((double) (usage.nvcsw - state->vcswprev) / dt + 0.5);
|
||||||
|
state->s.ivcsw = (uint32_t) ((double) (usage.nivcsw - state->ivcswprev) / dt + 0.5);
|
||||||
|
state->vcswprev = (uint32_t) usage.nvcsw;
|
||||||
|
state->ivcswprev = (uint32_t) usage.nivcsw;
|
||||||
state->s.cpu._length = 0;
|
state->s.cpu._length = 0;
|
||||||
for (size_t i = 0; i < state->nthreads; i++)
|
for (size_t i = 0; i < state->nthreads; i++)
|
||||||
{
|
{
|
||||||
|
@ -187,14 +197,18 @@ struct record_cputime_state *record_cputime_new (dds_entity_t wr)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct record_cputime_state *state = malloc (sizeof (*state));
|
struct record_cputime_state *state = malloc (sizeof (*state));
|
||||||
|
ddsrt_rusage_t usage;
|
||||||
|
if (ddsrt_getrusage (DDSRT_RUSAGE_SELF, &usage) < 0)
|
||||||
|
usage.nvcsw = usage.nivcsw = 0;
|
||||||
state->tprev = dds_time ();
|
state->tprev = dds_time ();
|
||||||
state->wr = wr;
|
state->wr = wr;
|
||||||
|
state->vcswprev = (uint32_t) usage.nvcsw;
|
||||||
|
state->ivcswprev = (uint32_t) usage.nivcsw;
|
||||||
state->threads = malloc ((size_t) n * sizeof (*state->threads));
|
state->threads = malloc ((size_t) n * sizeof (*state->threads));
|
||||||
state->nthreads = 0;
|
state->nthreads = 0;
|
||||||
for (int32_t i = 0; i < n; i++)
|
for (int32_t i = 0; i < n; i++)
|
||||||
{
|
{
|
||||||
struct record_cputime_state_thr * const thr = &state->threads[state->nthreads];
|
struct record_cputime_state_thr * const thr = &state->threads[state->nthreads];
|
||||||
ddsrt_rusage_t usage;
|
|
||||||
if (ddsrt_getrusage_anythread (tids[i], &usage) < 0)
|
if (ddsrt_getrusage_anythread (tids[i], &usage) < 0)
|
||||||
continue;
|
continue;
|
||||||
thr->tid = tids[i];
|
thr->tid = tids[i];
|
||||||
|
|
|
@ -1524,29 +1524,36 @@ static void sigxfsz_handler (int sig __attribute__ ((unused)))
|
||||||
static void usage (void)
|
static void usage (void)
|
||||||
{
|
{
|
||||||
printf ("\
|
printf ("\
|
||||||
%s help\n\
|
%s help (this text)\n\
|
||||||
|
%s sanity (ping 1Hz)\n\
|
||||||
%s [OPTIONS] MODE...\n\
|
%s [OPTIONS] MODE...\n\
|
||||||
\n\
|
\n\
|
||||||
OPTIONS:\n\
|
OPTIONS:\n\
|
||||||
|
-L allow matching with endpoints in the same process\n\
|
||||||
|
to get throughput/latency in the same ddsperf process\n\
|
||||||
-T KS|K32|K256|OU topic (KS is default):\n\
|
-T KS|K32|K256|OU topic (KS is default):\n\
|
||||||
KS seq num, key value, sequence-of-octets\n\
|
KS seq num, key value, sequence-of-octets\n\
|
||||||
K32 seq num, key value, array of 24 octets\n\
|
K32 seq num, key value, array of 24 octets\n\
|
||||||
K256 seq num, key value, array of 248 octets\n\
|
K256 seq num, key value, array of 248 octets\n\
|
||||||
OU seq num\n\
|
OU seq num\n\
|
||||||
-L allow matching with local endpoints\n\
|
-n N number of key values to use for data (only for\n\
|
||||||
|
topics with a key value)\n\
|
||||||
-u best-effort instead of reliable\n\
|
-u best-effort instead of reliable\n\
|
||||||
-k all|N keep-all or keep-last-N for data (ping/pong is\n\
|
-k all|N keep-all or keep-last-N for data (ping/pong is\n\
|
||||||
always keep-last-1)\n\
|
always keep-last-1)\n\
|
||||||
-n N number of key values to use for data (only for\n\
|
-c subscribe to CPU stats from peers and show them\n\
|
||||||
topics with a key value)\n\
|
-d DEV:BW report network load for device DEV with nominal\n\
|
||||||
|
bandwidth BW in bits/s (e.g., eth0:1e9)\n\
|
||||||
-D DUR run for at most DUR seconds\n\
|
-D DUR run for at most DUR seconds\n\
|
||||||
-N COUNT require at least COUNT matching participants\n\
|
-N COUNT require at least COUNT matching participants\n\
|
||||||
-M DUR require those participants to match within DUR seconds\n\
|
-M DUR require those participants to match within DUR seconds\n\
|
||||||
|
-R TREF timestamps in the output relative to TREF instead of\n\
|
||||||
|
process start\n\
|
||||||
\n\
|
\n\
|
||||||
MODE... is zero or more of:\n\
|
MODE... is zero or more of:\n\
|
||||||
ping [R[Hz]] [size N] [waitset|listener]\n\
|
ping [R[Hz]] [size S] [waitset|listener]\n\
|
||||||
Send a ping upon receiving all expected pongs, or send a ping at\n\
|
Send a ping upon receiving all expected pongs, or send a ping at\n\
|
||||||
rate R (optionally suffixed with Hz). The triggering mode is either\n\
|
rate R (optionally suffixed with Hz/kHz). The triggering mode is either\n\
|
||||||
a listener (default, unless -L has been specified) or a waitset.\n\
|
a listener (default, unless -L has been specified) or a waitset.\n\
|
||||||
pong [waitset|listener]\n\
|
pong [waitset|listener]\n\
|
||||||
A \"dummy\" mode that serves two purposes: configuring the triggering.\n\
|
A \"dummy\" mode that serves two purposes: configuring the triggering.\n\
|
||||||
|
@ -1555,11 +1562,12 @@ MODE... is zero or more of:\n\
|
||||||
sub [waitset|listener|polling]\n\
|
sub [waitset|listener|polling]\n\
|
||||||
Subscribe to data, with calls to take occurring either in a listener\n\
|
Subscribe to data, with calls to take occurring either in a listener\n\
|
||||||
(default), when a waitset is triggered, or by polling at 1kHz.\n\
|
(default), when a waitset is triggered, or by polling at 1kHz.\n\
|
||||||
pub [R[Hz]] [size N] [burst N] [[ping] X%%]\n\
|
pub [R[Hz]] [size S] [burst N] [[ping] X%%]\n\
|
||||||
Publish bursts of data at rate R, optionally suffixed with Hz. If\n\
|
Publish bursts of data at rate R, optionally suffixed with Hz/kHz. If\n\
|
||||||
no rate is given or R is \"inf\", data is published as fast as\n\
|
no rate is given or R is \"inf\", data is published as fast as\n\
|
||||||
possible. Each burst is a single sample by default, but can be set\n\
|
possible. Each burst is a single sample by default, but can be set\n\
|
||||||
to larger value using \"burst N\".\n\
|
to larger value using \"burst N\". Sample size is controlled using\n\
|
||||||
|
\"size S\", S may be suffixed with k/M/kB/MB/KiB/MiB.\n\
|
||||||
If desired, a fraction of the samples can be treated as if it were a\n\
|
If desired, a fraction of the samples can be treated as if it were a\n\
|
||||||
ping, for this, specify a percentage either as \"ping X%%\" (the\n\
|
ping, for this, specify a percentage either as \"ping X%%\" (the\n\
|
||||||
\"ping\" keyword is optional, the %% sign is not).\n\
|
\"ping\" keyword is optional, the %% sign is not).\n\
|
||||||
|
@ -1569,8 +1577,23 @@ MODE... is zero or more of:\n\
|
||||||
the last one given determines it for all) and should be either 0 (minimal,\n\
|
the last one given determines it for all) and should be either 0 (minimal,\n\
|
||||||
equivalent to 12) or >= 12.\n\
|
equivalent to 12) or >= 12.\n\
|
||||||
\n\
|
\n\
|
||||||
If no MODE specified, it defaults to a 1Hz ping + responding to any pings.\n\
|
EXIT STATUS:\n\
|
||||||
", argv0, argv0);
|
\n\
|
||||||
|
0 all is well\n\
|
||||||
|
1 not enough peers discovered, other matching issues, unexpected sample\n\
|
||||||
|
loss detected\n\
|
||||||
|
2 unexpected failure of some DDS operation\n\
|
||||||
|
3 incorrect arguments\n\
|
||||||
|
\n\
|
||||||
|
EXAMPLES:\n\
|
||||||
|
ddsperf pub size 1k & ddsperf sub\n\
|
||||||
|
basic throughput test with 1024-bytes large samples\n\
|
||||||
|
ddsperf ping & ddsperf pong\n\
|
||||||
|
basic latency test\n\
|
||||||
|
ddsperf -L -TOU -D10 pub sub\n\
|
||||||
|
basic throughput test within the process with tiny, keyless samples,\n\
|
||||||
|
running for 10s\n\
|
||||||
|
", argv0, argv0, argv0);
|
||||||
fflush (stdout);
|
fflush (stdout);
|
||||||
exit (3);
|
exit (3);
|
||||||
}
|
}
|
||||||
|
@ -1628,18 +1651,57 @@ static int string_int_map_lookup (const struct string_int_map_elem *elems, const
|
||||||
return (match == SIZE_MAX) ? -1 : elems[match].value;
|
return (match == SIZE_MAX) ? -1 : elems[match].value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool set_simple_uint32 (int *xoptind, int xargc, char * const xargv[], const char *token, uint32_t *val)
|
struct multiplier {
|
||||||
|
const char *suffix;
|
||||||
|
int mult;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct multiplier frequency_units[] = {
|
||||||
|
{ "Hz", 1 },
|
||||||
|
{ "kHz", 1024 },
|
||||||
|
{ NULL, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct multiplier size_units[] = {
|
||||||
|
{ "B", 1 },
|
||||||
|
{ "k", 1024 },
|
||||||
|
{ "M", 1048576 },
|
||||||
|
{ "kB", 1024 },
|
||||||
|
{ "KiB", 1024 },
|
||||||
|
{ "MB", 1048576 },
|
||||||
|
{ "MiB", 1048576 },
|
||||||
|
{ NULL, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static int lookup_multiplier (const struct multiplier *units, const char *suffix)
|
||||||
|
{
|
||||||
|
while (*suffix == ' ')
|
||||||
|
suffix++;
|
||||||
|
if (*suffix == 0)
|
||||||
|
return 1;
|
||||||
|
else if (units == NULL)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (size_t i = 0; units[i].suffix; i++)
|
||||||
|
if (strcmp (units[i].suffix, suffix) == 0)
|
||||||
|
return units[i].mult;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool set_simple_uint32 (int *xoptind, int xargc, char * const xargv[], const char *token, const struct multiplier *units, uint32_t *val)
|
||||||
{
|
{
|
||||||
if (strcmp (xargv[*xoptind], token) != 0)
|
if (strcmp (xargv[*xoptind], token) != 0)
|
||||||
return false;
|
return false;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unsigned x;
|
unsigned x;
|
||||||
int pos;
|
int pos, mult;
|
||||||
if (++(*xoptind) == xargc)
|
if (++(*xoptind) == xargc)
|
||||||
error3 ("argument missing in %s specification\n", token);
|
error3 ("argument missing in %s specification\n", token);
|
||||||
if (sscanf (xargv[*xoptind], "%u%n", &x, &pos) == 1 && xargv[*xoptind][pos] == 0)
|
if (sscanf (xargv[*xoptind], "%u%n", &x, &pos) == 1 && (mult = lookup_multiplier (units, xargv[*xoptind] + pos)) > 0)
|
||||||
*val = x;
|
*val = x * (unsigned) mult;
|
||||||
else
|
else
|
||||||
error3 ("%s: invalid %s specification\n", xargv[*xoptind], token);
|
error3 ("%s: invalid %s specification\n", xargv[*xoptind], token);
|
||||||
return true;
|
return true;
|
||||||
|
@ -1652,19 +1714,20 @@ static void set_mode_ping (int *xoptind, int xargc, char * const xargv[])
|
||||||
pingpongmode = SM_LISTENER;
|
pingpongmode = SM_LISTENER;
|
||||||
while (*xoptind < xargc && exact_string_int_map_lookup (modestrings, "mode string", xargv[*xoptind], false) == -1)
|
while (*xoptind < xargc && exact_string_int_map_lookup (modestrings, "mode string", xargv[*xoptind], false) == -1)
|
||||||
{
|
{
|
||||||
int pos;
|
int pos = 0, mult = 1;
|
||||||
double ping_rate;
|
double ping_rate;
|
||||||
if (strcmp (xargv[*xoptind], "inf") == 0)
|
if (strcmp (xargv[*xoptind], "inf") == 0 && lookup_multiplier (frequency_units, xargv[*xoptind] + 3) > 0)
|
||||||
{
|
{
|
||||||
ping_intv = 0;
|
ping_intv = 0;
|
||||||
}
|
}
|
||||||
else if (sscanf (xargv[*xoptind], "%lf%n", &ping_rate, &pos) == 1 && (xargv[*xoptind][pos] == 0 || strcmp (xargv[*xoptind] + pos, "Hz") == 0))
|
else if (sscanf (xargv[*xoptind], "%lf%n", &ping_rate, &pos) == 1 && (mult = lookup_multiplier (frequency_units, xargv[*xoptind] + pos)) > 0)
|
||||||
{
|
{
|
||||||
|
ping_rate *= mult;
|
||||||
if (ping_rate == 0) ping_intv = DDS_INFINITY;
|
if (ping_rate == 0) ping_intv = DDS_INFINITY;
|
||||||
else if (ping_rate > 0) ping_intv = (dds_duration_t) (1e9 / ping_rate + 0.5);
|
else if (ping_rate > 0) ping_intv = (dds_duration_t) (1e9 / ping_rate + 0.5);
|
||||||
else error3 ("%s: invalid ping rate\n", xargv[*xoptind]);
|
else error3 ("%s: invalid ping rate\n", xargv[*xoptind]);
|
||||||
}
|
}
|
||||||
else if (set_simple_uint32 (xoptind, xargc, xargv, "size", &baggagesize))
|
else if (set_simple_uint32 (xoptind, xargc, xargv, "size", size_units, &baggagesize))
|
||||||
{
|
{
|
||||||
/* no further work needed */
|
/* no further work needed */
|
||||||
}
|
}
|
||||||
|
@ -1709,22 +1772,22 @@ static void set_mode_pub (int *xoptind, int xargc, char * const xargv[])
|
||||||
ping_frac = 0;
|
ping_frac = 0;
|
||||||
while (*xoptind < xargc && exact_string_int_map_lookup (modestrings, "mode string", xargv[*xoptind], false) == -1)
|
while (*xoptind < xargc && exact_string_int_map_lookup (modestrings, "mode string", xargv[*xoptind], false) == -1)
|
||||||
{
|
{
|
||||||
int pos = 0;
|
int pos = 0, mult = 1;
|
||||||
double r;
|
double r;
|
||||||
if (strcmp (xargv[*xoptind], "inf") == 0 || strcmp (xargv[*xoptind], "infHz") == 0)
|
if (strncmp (xargv[*xoptind], "inf", 3) == 0 && lookup_multiplier (frequency_units, xargv[*xoptind] + 3) > 0)
|
||||||
{
|
{
|
||||||
pub_rate = HUGE_VAL;
|
pub_rate = HUGE_VAL;
|
||||||
}
|
}
|
||||||
else if (sscanf (xargv[*xoptind], "%lf%n", &r, &pos) == 1 && (xargv[*xoptind][pos] == 0 || strcmp (xargv[*xoptind] + pos, "Hz") == 0))
|
else if (sscanf (xargv[*xoptind], "%lf%n", &r, &pos) == 1 && (mult = lookup_multiplier (frequency_units, xargv[*xoptind] + pos)) > 0)
|
||||||
{
|
{
|
||||||
if (r < 0) error3 ("%s: invalid publish rate\n", xargv[*xoptind]);
|
if (r < 0) error3 ("%s: invalid publish rate\n", xargv[*xoptind]);
|
||||||
pub_rate = r;
|
pub_rate = r * mult;
|
||||||
}
|
}
|
||||||
else if (set_simple_uint32 (xoptind, xargc, xargv, "burst", &burstsize))
|
else if (set_simple_uint32 (xoptind, xargc, xargv, "burst", NULL, &burstsize))
|
||||||
{
|
{
|
||||||
/* no further work needed */
|
/* no further work needed */
|
||||||
}
|
}
|
||||||
else if (set_simple_uint32 (xoptind, xargc, xargv, "size", &baggagesize))
|
else if (set_simple_uint32 (xoptind, xargc, xargv, "size", size_units, &baggagesize))
|
||||||
{
|
{
|
||||||
/* no further work needed */
|
/* no further work needed */
|
||||||
}
|
}
|
||||||
|
@ -1753,7 +1816,7 @@ static void set_mode (int xoptind, int xargc, char * const xargv[])
|
||||||
pub_rate = 0.0;
|
pub_rate = 0.0;
|
||||||
submode = SM_NONE;
|
submode = SM_NONE;
|
||||||
pingpongmode = SM_LISTENER;
|
pingpongmode = SM_LISTENER;
|
||||||
ping_intv = (xoptind == xargc) ? DDS_SECS (1) : DDS_INFINITY;
|
ping_intv = DDS_INFINITY;
|
||||||
ping_frac = 0;
|
ping_frac = 0;
|
||||||
while (xoptind < xargc && (code = exact_string_int_map_lookup (modestrings, "mode string", xargv[xoptind], true)) != -1)
|
while (xoptind < xargc && (code = exact_string_int_map_lookup (modestrings, "mode string", xargv[xoptind], true)) != -1)
|
||||||
{
|
{
|
||||||
|
@ -1793,8 +1856,6 @@ int main (int argc, char *argv[])
|
||||||
|
|
||||||
argv0 = argv[0];
|
argv0 = argv[0];
|
||||||
|
|
||||||
if (argc == 2 && strcmp (argv[1], "help") == 0)
|
|
||||||
usage ();
|
|
||||||
while ((opt = getopt (argc, argv, "cd:D:n:k:uLK:T:M:N:R:h")) != EOF)
|
while ((opt = getopt (argc, argv, "cd:D:n:k:uLK:T:M:N:R:h")) != EOF)
|
||||||
{
|
{
|
||||||
switch (opt)
|
switch (opt)
|
||||||
|
@ -1829,7 +1890,18 @@ int main (int argc, char *argv[])
|
||||||
default: error3 ("-%c: unknown option\n", opt); break;
|
default: error3 ("-%c: unknown option\n", opt); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
set_mode (optind, argc, argv);
|
|
||||||
|
if (optind == argc || (optind + 1 == argc && strcmp (argv[optind], "help") == 0))
|
||||||
|
usage ();
|
||||||
|
else if (optind + 1 == argc && strcmp (argv[optind], "sanity") == 0)
|
||||||
|
{
|
||||||
|
char * const sanity[] = { "ping", "1Hz" };
|
||||||
|
set_mode (0, 2, sanity);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
set_mode (optind, argc, argv);
|
||||||
|
}
|
||||||
|
|
||||||
if (nkeyvals == 0)
|
if (nkeyvals == 0)
|
||||||
nkeyvals = 1;
|
nkeyvals = 1;
|
||||||
|
|
|
@ -40,6 +40,8 @@ struct CPUStats
|
||||||
string hostname;
|
string hostname;
|
||||||
unsigned long pid;
|
unsigned long pid;
|
||||||
double maxrss;
|
double maxrss;
|
||||||
|
unsigned long vcsw;
|
||||||
|
unsigned long ivcsw;
|
||||||
boolean some_above;
|
boolean some_above;
|
||||||
sequence<CPUStatThread> cpu;
|
sequence<CPUStatThread> cpu;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue