Make max_dispatch_interval able to apply only to low-priority events

Suggested by Alexander Drozdov
This commit is contained in:
Nick Mathewson 2011-08-11 12:38:47 -04:00
parent a9866aa8c1
commit a37a0c0e35
3 changed files with 34 additions and 6 deletions

View File

@ -275,6 +275,7 @@ struct event_base {
struct timeval max_dispatch_time; struct timeval max_dispatch_time;
int max_dispatch_callbacks; int max_dispatch_callbacks;
int limit_callbacks_after_prio;
/* Notify main thread to wake up break, etc. */ /* Notify main thread to wake up break, etc. */
/** True if the base already has a pending notify, and we don't need /** True if the base already has a pending notify, and we don't need
@ -304,6 +305,7 @@ struct event_config {
int n_cpus_hint; int n_cpus_hint;
struct timeval max_dispatch_interval; struct timeval max_dispatch_interval;
int max_dispatch_callbacks; int max_dispatch_callbacks;
int limit_callbacks_after_prio;
enum event_method_feature require_features; enum event_method_feature require_features;
enum event_base_config_flag flags; enum event_base_config_flag flags;
}; };

22
event.c
View File

@ -587,16 +587,23 @@ event_base_new_with_config(const struct event_config *cfg)
should_check_environment = should_check_environment =
!(cfg && (cfg->flags & EVENT_BASE_FLAG_IGNORE_ENV)); !(cfg && (cfg->flags & EVENT_BASE_FLAG_IGNORE_ENV));
if (cfg) if (cfg) {
memcpy(&base->max_dispatch_time, memcpy(&base->max_dispatch_time,
&cfg->max_dispatch_interval, sizeof(struct timeval)); &cfg->max_dispatch_interval, sizeof(struct timeval));
else base->limit_callbacks_after_prio =
cfg->limit_callbacks_after_prio;
} else {
base->max_dispatch_time.tv_sec = -1; base->max_dispatch_time.tv_sec = -1;
base->limit_callbacks_after_prio = 1;
}
if (cfg && cfg->max_dispatch_callbacks >= 0) { if (cfg && cfg->max_dispatch_callbacks >= 0) {
base->max_dispatch_callbacks = cfg->max_dispatch_callbacks; base->max_dispatch_callbacks = cfg->max_dispatch_callbacks;
} else { } else {
base->max_dispatch_callbacks = INT_MAX; base->max_dispatch_callbacks = INT_MAX;
} }
if (base->max_dispatch_callbacks == INT_MAX &&
base->max_dispatch_time.tv_sec == -1)
base->limit_callbacks_after_prio = INT_MAX;
for (i = 0; eventops[i] && !base->evbase; i++) { for (i = 0; eventops[i] && !base->evbase; i++) {
if (cfg != NULL) { if (cfg != NULL) {
@ -924,6 +931,7 @@ event_config_new(void)
TAILQ_INIT(&cfg->entries); TAILQ_INIT(&cfg->entries);
cfg->max_dispatch_interval.tv_sec = -1; cfg->max_dispatch_interval.tv_sec = -1;
cfg->max_dispatch_callbacks = INT_MAX; cfg->max_dispatch_callbacks = INT_MAX;
cfg->limit_callbacks_after_prio = 1;
return (cfg); return (cfg);
} }
@ -995,7 +1003,7 @@ event_config_set_num_cpus_hint(struct event_config *cfg, int cpus)
int int
event_config_set_max_dispatch_interval(struct event_config *cfg, event_config_set_max_dispatch_interval(struct event_config *cfg,
const struct timeval *max_interval, int max_callbacks) const struct timeval *max_interval, int max_callbacks, int min_priority)
{ {
if (max_interval) if (max_interval)
memcpy(&cfg->max_dispatch_interval, max_interval, memcpy(&cfg->max_dispatch_interval, max_interval,
@ -1003,7 +1011,10 @@ event_config_set_max_dispatch_interval(struct event_config *cfg,
else else
cfg->max_dispatch_interval.tv_sec = -1; cfg->max_dispatch_interval.tv_sec = -1;
cfg->max_dispatch_callbacks = cfg->max_dispatch_callbacks =
max_callbacks >= 0 ? max_callbacks : INT_MAX ; max_callbacks >= 0 ? max_callbacks : INT_MAX;
if (min_priority <= 0)
min_priority = 1;
cfg->limit_callbacks_after_prio = min_priority;
return (0); return (0);
} }
@ -1428,6 +1439,7 @@ event_process_active(struct event_base *base)
const struct timeval *endtime; const struct timeval *endtime;
struct timeval tv; struct timeval tv;
const int maxcb = base->max_dispatch_callbacks; const int maxcb = base->max_dispatch_callbacks;
const int limit_after_prio = base->limit_callbacks_after_prio;
if (base->max_dispatch_time.tv_sec >= 0) { if (base->max_dispatch_time.tv_sec >= 0) {
evutil_gettimeofday(&tv, NULL); evutil_gettimeofday(&tv, NULL);
evutil_timeradd(&base->max_dispatch_time, &tv, &tv); evutil_timeradd(&base->max_dispatch_time, &tv, &tv);
@ -1439,7 +1451,7 @@ event_process_active(struct event_base *base)
for (i = 0; i < base->nactivequeues; ++i) { for (i = 0; i < base->nactivequeues; ++i) {
if (TAILQ_FIRST(&base->activequeues[i]) != NULL) { if (TAILQ_FIRST(&base->activequeues[i]) != NULL) {
activeq = &base->activequeues[i]; activeq = &base->activequeues[i];
if (i == 0) if (i < limit_after_prio)
c = event_process_active_single_queue(base, activeq, c = event_process_active_single_queue(base, activeq,
INT_MAX, NULL); INT_MAX, NULL);
else else

View File

@ -550,9 +550,23 @@ int event_config_set_num_cpus_hint(struct event_config *cfg, int cpus);
* avoid priority inversions where multiple low-priority events keep us from * avoid priority inversions where multiple low-priority events keep us from
* polling for high-priority events, but at the expense of slightly decreasing * polling for high-priority events, but at the expense of slightly decreasing
* the throughput. Use it with caution! * the throughput. Use it with caution!
*
* @param cfg The event_base configuration object.
* @param max_interval An interval after which Libevent should stop running
* callbacks and check for more events, or NULL if there should be
* no such interval.
* @param max_callbacks A number of callbacks after which Libevent should
* stop running callbacks and check for more events, or -1 if there
* should be no such limit.
* @param min_priority A priority below which max_interval and max_callbacks
* should not be enforced. If this is set to 0, they are enforced
* for events of every priority; if it's set to 1, they're enforced
* for events of priority 1 and above, and so on.
* @return 0 on success, -1 on failure.
**/ **/
int event_config_set_max_dispatch_interval(struct event_config *cfg, int event_config_set_max_dispatch_interval(struct event_config *cfg,
const struct timeval *max_interval, int max_callbacks); const struct timeval *max_interval, int max_callbacks,
int min_priority);
/** /**
Initialize the event API. Initialize the event API.