31#ifdef ENABLE_PERFORMANCE_METRICS
38static const char *metric_names[] = {
"PERF_BIO_READ_PLAINTEXT",
39 "PERF_BIO_WRITE_PLAINTEXT",
40 "PERF_BIO_READ_CIPHERTEXT",
41 "PERF_BIO_WRITE_CIPHERTEXT",
42 "PERF_TLS_MULTI_PROCESS",
45 "PERF_MULTI_CREATE_INSTANCE",
46 "PERF_MULTI_CLOSE_INSTANCE",
47 "PERF_MULTI_SHOW_STATS",
57 "PERF_PROC_OUT_TUN_MTCP" };
62#define PS_METER_RUNNING 1
63#define PS_METER_INTERRUPTED 2
80static struct perf_set perf_set;
82static void perf_print_state(
int lev);
85get_stack_index(
int sdelta)
87 const int sindex = perf_set.stack_len + sdelta;
88 if (sindex >= 0 && sindex < STACK_N)
99get_perf_index(
int sdelta)
101 const int sindex = get_stack_index(sdelta);
104 const int pindex = perf_set.stack[sindex];
105 if (pindex >= 0 && pindex <
PERF_N)
123 const int pindex = get_perf_index(sdelta);
126 return &perf_set.perf[pindex];
135push_perf_index(
int pindex)
137 const int sindex = get_stack_index(0);
138 const int newlen = get_stack_index(1);
139 if (sindex >= 0 && newlen >= 0 && pindex >= 0 && pindex <
PERF_N)
142 for (
i = 0;
i < sindex; ++
i)
144 if (perf_set.stack[
i] == pindex)
147 msg(
M_FATAL,
"PERF: push_perf_index %s failed", metric_names[pindex]);
151 perf_set.stack[sindex] = pindex;
152 perf_set.stack_len = newlen;
156 msg(
M_FATAL,
"PERF: push_perf_index: stack push error");
163 const int newlen = get_stack_index(-1);
166 perf_set.stack_len = newlen;
170 msg(
M_FATAL,
"PERF: pop_perf_index: stack pop error");
175state_must_be(
const struct perf *p,
const int wanted)
177 if (p->state != wanted)
179 msg(
M_FATAL,
"PERF: bad state actual=%d wanted=%d", p->state, wanted);
184update_sofar(
struct perf *p)
186 struct timeval current;
187 ASSERT(!gettimeofday(¤t, NULL));
188 p->sofar += (double)
tv_subtract(¤t, &p->start, 600) / 1000000.0;
193perf_start(
struct perf *p)
195 state_must_be(p, PS_INITIAL);
196 ASSERT(!gettimeofday(&p->start, NULL));
198 p->state = PS_METER_RUNNING;
202perf_stop(
struct perf *p)
204 state_must_be(p, PS_METER_RUNNING);
207 if (p->sofar > p->max)
213 p->state = PS_INITIAL;
217perf_interrupt(
struct perf *p)
219 state_must_be(p, PS_METER_RUNNING);
221 p->state = PS_METER_INTERRUPTED;
225perf_resume(
struct perf *p)
227 state_must_be(p, PS_METER_INTERRUPTED);
228 ASSERT(!gettimeofday(&p->start, NULL));
229 p->state = PS_METER_RUNNING;
239 push_perf_index(type);
248 perf_interrupt(prev);
277 msg(
M_INFO,
"LATENCY PROFILE (mean and max are in milliseconds)");
280 struct perf *p = &perf_set.perf[
i];
283 const double mean = p->sum / p->count;
284 msg(
M_INFO,
"%s n=%.0f mean=%.3f max=%.3f", metric_names[
i], p->count, mean * 1000.0,
291perf_print_state(
int lev)
295 msg(lev,
"PERF STATE");
297 for (
i = 0;
i < perf_set.stack_len; ++
i)
299 const int j = perf_set.stack[
i];
300 const struct perf *p = &perf_set.perf[j];
301 msg(lev,
"[%d] %s state=%d start=%s sofar=%f sum=%f max=%f count=%f",
i, metric_names[j],
302 p->state,
tv_string(&p->start, &
gc), p->sofar, p->sum, p->max, p->count);
static void gc_free(struct gc_arena *a)
static struct gc_arena gc_new(void)
const char * tv_string(const struct timeval *tv, struct gc_arena *gc)
static int tv_subtract(const struct timeval *tv1, const struct timeval *tv2, const unsigned int max_seconds)
static void tv_clear(struct timeval *tv)
static void perf_push(int type)
static void perf_output_results(void)
static void perf_pop(void)
Garbage collection arena used to keep track of dynamically allocated memory.