Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Write thoughput data of ddsperf to csv file specified on command line via -f option #583

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
207 changes: 170 additions & 37 deletions src/tools/ddsperf/cputime.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,49 +27,26 @@
#include "cputime.h"
#include "ddsperf_types.h"

static void print_one (char *line, size_t sz, size_t *pos, const char *name, double du, double ds)
static void print_one (FILE *fp, char *line, size_t sz, size_t *pos, const char *name, double du, double ds)
{
if (*pos < sz)
*pos += (size_t) snprintf (line + *pos, sz - *pos, " %s:%.0f%%+%.0f%%", name, 100.0 * du, 100.0 * ds);
}

bool print_cputime (const struct CPUStats *s, const char *prefix, bool print_host, bool is_fresh)
{
if (!s->some_above)
return false;
else
{
char line[512];
size_t pos = 0;
pos += (size_t) snprintf (line + pos, sizeof (line) - pos, "%s", prefix);
if (!is_fresh)
pos += (size_t) snprintf (line + pos, sizeof (line) - pos, " (stale)");
if (print_host)
if (fp == NULL)
{
int n = (int) strlen (s->hostname);
if (n > 100) n = 100;
pos += (size_t) snprintf (line + pos, sizeof (line) - pos, " @%*.*s:%"PRIu32, n, n, s->hostname, s->pid);
}
if (s->maxrss > 1048576)
pos += (size_t) snprintf (line + pos, sizeof (line) - pos, " rss:%.1fMB", s->maxrss / 1048576.0);
else if (s->maxrss > 1024)
pos += (size_t) snprintf (line + pos, sizeof (line) - pos, " rss:%.0fkB", s->maxrss / 1024.0);
else {
/* non-sensical value -- presumably maxrss is not available */
*pos += (size_t) snprintf (line + *pos, sz - *pos, " %s:%.0f%%+%.0f%%", name, 100.0 * du, 100.0 * ds);
}
pos += (size_t) snprintf (line + pos, sizeof (line) - pos, " vcsw:%"PRIu32" ivcsw:%"PRIu32, s->vcsw, s->ivcsw);
const size_t init_pos = pos;
for (uint32_t i = 0; i < s->cpu._length; i++)
else
{
struct CPUStatThread * const thr = &s->cpu._buffer[i];
print_one (line, sizeof (line), &pos, thr->name, thr->u_pct / 100.0, thr->s_pct / 100.0);
*pos += (size_t) snprintf (line + *pos, sz - *pos, ",%s,%.0f,%.0f", name, 100.0 * du, 100.0 * ds);
}
if (pos > init_pos)
puts (line);
return true;
}
}

static void print_one_empty_entry (char *line, size_t sz, size_t *pos)
{
*pos += (size_t) snprintf (line + *pos, sz - *pos, ",,,");
}

#if DDSRT_HAVE_RUSAGE && DDSRT_HAVE_THREAD_LIST

struct record_cputime_state_thr {
Expand Down Expand Up @@ -113,7 +90,7 @@ static bool above_threshold (double *max, double *du_skip, double *ds_skip, doub
}
}

bool record_cputime (struct record_cputime_state *state, const char *prefix, dds_time_t tnow)
bool record_cputime (FILE *fp, struct record_cputime_state *state, const char *prefix, dds_time_t tnow, bool data_changed, bool *cputime_changed)
{
if (state == NULL)
return false;
Expand All @@ -139,7 +116,9 @@ bool record_cputime (struct record_cputime_state *state, const char *prefix, dds
{
struct record_cputime_state_thr * const thr = &state->threads[i];
if (ddsrt_getrusage_anythread (thr->tid, &usage) < 0)
{
continue;
}

const double ut = (double) usage.utime / 1e9;
const double st = (double) usage.stime / 1e9;
Expand All @@ -154,17 +133,16 @@ bool record_cputime (struct record_cputime_state *state, const char *prefix, dds
first time the thread pops up in the CPU usage works around the timing
problem. */
if (thr->name[0] == 0)
{
if (ddsrt_thread_getname_anythread (thr->tid, thr->name, sizeof (thr->name)) < 0)
{
du_skip += du;
ds_skip += ds;
continue;
}
}

struct CPUStatThread * const x = &state->s.cpu._buffer[state->s.cpu._length++];
x->name = thr->name;
x->tid = (uint32_t) thr->tid;
x->u_pct = (int) (100.0 * du + 0.5);
x->s_pct = (int) (100.0 * ds + 0.5);
}
Expand All @@ -180,7 +158,7 @@ bool record_cputime (struct record_cputime_state *state, const char *prefix, dds
state->tprev = tnow;
state->s.some_above = some_above;
(void) dds_write (state->wr, &state->s);
return print_cputime (&state->s, prefix, false, true);
return print_cputime (fp, &state->s, state, prefix, false, true, data_changed, cputime_changed, false);
}

double record_cputime_read_rss (const struct record_cputime_state *state)
Expand All @@ -193,13 +171,17 @@ struct record_cputime_state *record_cputime_new (dds_entity_t wr)
ddsrt_thread_list_id_t tids[100];
dds_return_t n;
if ((n = ddsrt_thread_list (tids, sizeof (tids) / sizeof (tids[0]))) <= 0)
{
fprintf (stderr, "ddsrt_thread_list returned %d\n", n);
return NULL;
}
else if (n > (dds_return_t) (sizeof (tids) / sizeof (tids[0])))
{
fprintf (stderr, "way more threads than expected\n");
return NULL;
}

printf("%s: number of threads: %d\n", __func__, (int)n);
struct record_cputime_state *state = malloc (sizeof (*state));
ddsrt_rusage_t usage;
if (ddsrt_getrusage (DDSRT_RUSAGE_SELF, &usage) < 0)
Expand Down Expand Up @@ -253,6 +235,7 @@ bool record_cputime (struct record_cputime_state *state, const char *prefix, dds
(void) state;
(void) prefix;
(void) tnow;
return false;
}

double record_cputime_read_rss (const struct record_cputime_state *state)
Expand All @@ -264,6 +247,7 @@ double record_cputime_read_rss (const struct record_cputime_state *state)
struct record_cputime_state *record_cputime_new (dds_entity_t wr)
{
(void) wr;
return NULL;
}

void record_cputime_free (struct record_cputime_state *state)
Expand All @@ -272,3 +256,152 @@ void record_cputime_free (struct record_cputime_state *state)
}

#endif

bool print_cputime (FILE *fp, const struct CPUStats *s, struct record_cputime_state *state, const char *prefix, bool print_host, bool is_fresh, bool data_changed, bool *cputime_changed, bool read)
{
*cputime_changed = false;
if (!s->some_above)
return false;
else
{
char line[512];
char line_fp[512];
size_t pos = 0;
size_t pos_fp = 0;
const size_t init_pos = pos;
const size_t init_pos_fp = pos_fp;
pos += (size_t) snprintf (line + pos, sizeof (line) - pos, "%s", prefix);
if (!is_fresh)
pos += (size_t) snprintf (line + pos, sizeof (line) - pos, " (stale)");
if (print_host)
{
data_changed = true;
int n = (int) strlen (s->hostname);
if (n > 100) n = 100;
pos += (size_t) snprintf (line + pos, sizeof (line) - pos, " @%-*.*s:%"PRIu32, n, n, s->hostname, s->pid);
if (fp != NULL)
{
if (read)
{
dds_time_t tnow = dds_time ();
int64_t tsec = (int64_t)(tnow / 1000000000);
int64_t nsec = (int64_t)(tnow % 1000000000);
char hostname[64];
ddsrt_pid_t pid = ddsrt_getpid ();
if (ddsrt_gethostname (hostname, sizeof (hostname)) != DDS_RETCODE_OK)
{
snprintf (hostname, sizeof (hostname), "%s", "<unknown>");
}
pos_fp += (size_t) snprintf (line_fp + pos_fp, sizeof (line_fp) - pos_fp,
"%"PRId64".%06"PRId64",%s,%"PRIdPID",,,,,,,,,,",
/* col01: epoch */tsec, nsec / 1000,
/* col02: hostname */hostname,
/* col03: pid */pid
/* col04: (empty) */
/* col05: (empty) */
/* col06: (empty) */
/* col07: (empty) */
/* col08: (empty) */
/* col09: (empty) */
/* col10: (empty) */
/* col11: (empty) */
/* col12: (empty) */
/* col12: (empty) */
/* col13: (empty) */);
}
pos_fp += (size_t) snprintf (line_fp + pos_fp, sizeof (line_fp) - pos_fp,
",@%-*.*s:%"PRIu32, n, n,
/* col14: hostname:pid */s->hostname, s->pid);
}
}
if (s->maxrss > 1048576)
{
pos += (size_t) snprintf (line + pos, sizeof (line) - pos, " rss:%.1fMB", s->maxrss / 1048576.0);
}
else if (s->maxrss > 1024)
{
pos += (size_t) snprintf (line + pos, sizeof (line) - pos, " rss:%.0fkB", s->maxrss / 1024.0);
}
else
{
/* non-sensical value -- presumably maxrss is not available */
}
if (fp != NULL)
{
pos_fp += (size_t) snprintf (line_fp + pos_fp, sizeof (line_fp) - pos_fp,
",%.0f",
/* col15: maxrss */s->maxrss);
}
pos += (size_t) snprintf (line + pos, sizeof (line) - pos, " vcsw:%"PRIu32" ivcsw:%"PRIu32, s->vcsw, s->ivcsw);
if (fp != NULL)
{
pos_fp += (size_t) snprintf (line_fp + pos_fp, sizeof (line_fp) - pos_fp,
",%"PRIu32",%"PRIu32",%d,%d",
/* col16: vcsw */s->vcsw,
/* col17: ivcsw */s->ivcsw,
/* col18: cpu.maximum */(int)s->cpu._maximum,
/* col19: cpu.length */(int)s->cpu._length);
}

for (uint32_t i = 0; i < s->cpu._length; i++)
{
struct CPUStatThread * const thr_i = &s->cpu._buffer[i];
print_one (NULL, line, sizeof (line), &pos, thr_i->name, thr_i->u_pct / 100.0, thr_i->s_pct / 100.0);
}

{
uint32_t i = 0;
for (i = 0; i < state->nthreads && i < 10; i++)
{
struct record_cputime_state_thr * const thr_i = &state->threads[i];
bool found = false;
for (uint32_t j = 0; j < s->cpu._length && j < 10; j++)
{
struct CPUStatThread * const thr_j = &s->cpu._buffer[j];
if ((ddsrt_thread_list_id_t)thr_j->tid == thr_i->tid)
{
print_one (NULL, line, sizeof (line), &pos, thr_j->name, thr_j->u_pct / 100.0, thr_j->s_pct / 100.0);
print_one (fp, line_fp, sizeof (line_fp), &pos_fp,
/* col20+(j*3) : name */thr_j->name,
/* col21+(j*3)+1: du */thr_j->u_pct / 100.0,
/* col22+(j*3)+2: ds */thr_j->s_pct / 100.0);
found = true;
break;
}
}
if (!found)
{
/* col20+(j*3) : (empty) */
/* col21+(j*3)+1: (empty) */
/* col22+(j*3)+2: (empty) */
print_one_empty_entry (line_fp, sizeof (line_fp), &pos_fp);
}
}
for (; i < 10; i++)
{
/* col20+(j*3) : (empty) */
/* col21+(j*3)+1: (empty) */
/* col22+(j*3)+2: (empty) */
print_one_empty_entry (line_fp, sizeof (line_fp), &pos_fp);
}
}

if (pos > init_pos)
{
puts (line);
}
if (pos_fp > init_pos_fp)
{
if (data_changed)
{
if (fp != NULL)
{
fprintf (fp, "%s%s", line_fp, read ? "\n" : "");
fflush (fp);
*cputime_changed = true;
}
}
}
return true;
}
}
4 changes: 2 additions & 2 deletions src/tools/ddsperf/cputime.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ struct record_cputime_state;

struct record_cputime_state *record_cputime_new (dds_entity_t wr);
void record_cputime_free (struct record_cputime_state *state);
bool record_cputime (struct record_cputime_state *state, const char *prefix, dds_time_t tnow);
bool record_cputime (FILE *fp, struct record_cputime_state *state, const char *prefix, dds_time_t tnow, bool data_changed, bool *cputime_changed);
double record_cputime_read_rss (const struct record_cputime_state *state);
bool print_cputime (const struct CPUStats *s, const char *prefix, bool print_host, bool is_fresh);
bool print_cputime (FILE *fp, const struct CPUStats *s, struct record_cputime_state *cputime_state, const char *prefix, bool print_host, bool is_fresh, bool data_changed, bool *cputime_changed, bool read);

#endif
Loading