<p>The Perf protocol is a generator of fake routes together with a time measurement
framework. Its purpose is to check BIRD performance and to benchmark filters.
-<p>This protocol runs in several steps. In each step, it generates 2^x routes,
+<p>Import mode of this protocol runs in several steps. In each step, it generates 2^x routes,
imports them into the appropriate table and withdraws them. The exponent x is configurable.
It runs the benchmark several times for the same x, then it increases x by one
until it gets too high, then it stops.
+<p>Export mode of this protocol repeats route refresh from table and measures how long it takes.
+
<p>Output data is logged on info level. There is a Perl script <cf>proto/perf/parse.pl</cf>
which may be handy to parse the data and draw some plots.
<p>Implementation of this protocol is experimental. Use with caution and do not keep
-any instance of Perf in production configs.
+any instance of Perf in production configs for long time. The config interface is also unstable
+and may change in future versions without warning.
<sect1>Configuration
<label id="perf-config">
<p><descrip>
+ <tag><label id="perf-mode">mode import|export</tag>
+ Set perf mode. Default: import
+
<tag><label id="perf-repeat">repeat <m/number/</tag>
Run this amount of iterations of the benchmark for every amount step. Default: 4
CF_DECLS
-CF_KEYWORDS(PERF, EXP, FROM, TO, REPEAT, THRESHOLD, MIN, MAX, KEEP)
+CF_KEYWORDS(PERF, EXP, FROM, TO, REPEAT, THRESHOLD, MIN, MAX, KEEP, MODE, IMPORT, EXPORT)
CF_GRAMMAR
PERF_CFG->threshold_max = 500 MS_;
PERF_CFG->threshold_min = 1 MS_;
PERF_CFG->keep = 0;
+ PERF_CFG->mode = PERF_MODE_IMPORT;
};
perf_proto:
| THRESHOLD MIN expr_us { PERF_CFG->threshold_min = $3; }
| THRESHOLD MAX expr_us { PERF_CFG->threshold_max = $3; }
| KEEP bool { PERF_CFG->keep = $2; }
+ | MODE IMPORT { PERF_CFG->mode = PERF_MODE_IMPORT; }
+ | MODE EXPORT { PERF_CFG->mode = PERF_MODE_EXPORT; }
;
ev_schedule(p->loop);
}
+static void
+perf_rt_notify(struct proto *P, struct channel *c UNUSED, struct network *net UNUSED, struct rte *new UNUSED, struct rte *old UNUSED)
+{
+ struct perf_proto *p = (struct perf_proto *) P;
+ p->exp++;
+ return;
+}
+
+static void
+perf_feed_begin(struct channel *c, int initial UNUSED)
+{
+ struct perf_proto *p = (struct perf_proto *) c->proto;
+
+ p->run++;
+ p->data = xmalloc(sizeof(struct timespec));
+ p->exp = 0;
+
+ clock_gettime(CLOCK_MONOTONIC, p->data);
+}
+
+static void
+perf_feed_end(struct channel *c)
+{
+ struct perf_proto *p = (struct perf_proto *) c->proto;
+ struct timespec ts_end;
+ clock_gettime(CLOCK_MONOTONIC, &ts_end);
+
+ s64 feedtime = timediff(p->data, &ts_end);
+
+ PLOG("feed n=%lu time=%lu", p->exp, feedtime);
+
+ if (p->run < p->repeat)
+ channel_request_feeding(c);
+ else
+ PLOG("feed done");
+}
+
static struct proto *
perf_init(struct proto_config *CF)
{
struct proto *P = proto_new(CF);
P->main_channel = proto_add_channel(P, proto_cf_main_channel(CF));
- P->ifa_notify = perf_ifa_notify;
struct perf_proto *p = (struct perf_proto *) P;
p->to = cf->to;
p->repeat = cf->repeat;
p->keep = cf->keep;
+ p->mode = cf->mode;
+
+ switch (p->mode) {
+ case PERF_MODE_IMPORT:
+ P->ifa_notify = perf_ifa_notify;
+ break;
+ case PERF_MODE_EXPORT:
+ P->rt_notify = perf_rt_notify;
+ P->feed_begin = perf_feed_begin;
+ P->feed_end = perf_feed_end;
+ break;
+ }
return P;
}
#ifndef _BIRD_PERF_H_
#define _BIRD_PERF_H_
+enum perf_mode {
+ PERF_MODE_IMPORT,
+ PERF_MODE_EXPORT,
+};
+
struct perf_config {
struct proto_config p;
btime threshold_min;
uint to;
uint repeat;
uint keep;
+ enum perf_mode mode;
};
struct perf_proto {
uint exp;
uint stop;
uint keep;
+ enum perf_mode mode;
};
#endif