Merge pull request #16750 from AspirinSJL/timer

Clean some timer code
reviewable/pr16187/r1
Juanli Shen 6 years ago committed by GitHub
commit 61b542f912
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 16
      src/core/lib/iomgr/timer_generic.cc
  2. 4
      src/core/lib/iomgr/timer_heap.cc
  3. 6
      src/core/lib/iomgr/timer_heap.h
  4. 8
      src/core/lib/iomgr/timer_manager.cc
  5. 4
      src/core/lib/iomgr/timer_manager.h

@ -48,22 +48,22 @@ grpc_core::TraceFlag grpc_timer_trace(false, "timer");
grpc_core::TraceFlag grpc_timer_check_trace(false, "timer_check");
/* A "timer shard". Contains a 'heap' and a 'list' of timers. All timers with
* deadlines earlier than 'queue_deadline" cap are maintained in the heap and
* deadlines earlier than 'queue_deadline_cap' are maintained in the heap and
* others are maintained in the list (unordered). This helps to keep the number
* of elements in the heap low.
*
* The 'queue_deadline_cap' gets recomputed periodically based on the timer
* stats maintained in 'stats' and the relevant timers are then moved from the
* 'list' to 'heap'
* 'list' to 'heap'.
*/
typedef struct {
gpr_mu mu;
grpc_time_averaged_stats stats;
/* All and only timers with deadlines <= this will be in the heap. */
/* All and only timers with deadlines < this will be in the heap. */
grpc_millis queue_deadline_cap;
/* The deadline of the next timer due in this shard */
/* The deadline of the next timer due in this shard. */
grpc_millis min_deadline;
/* Index of this timer_shard in the g_shard_queue */
/* Index of this timer_shard in the g_shard_queue. */
uint32_t shard_queue_index;
/* This holds all timers with deadlines < queue_deadline_cap. Timers in this
list have the top bit of their deadline set to 0. */
@ -85,7 +85,7 @@ static timer_shard** g_shard_queue;
#ifndef NDEBUG
/* == Hash table for duplicate timer detection == */
/* == DEBUG ONLY: hash table for duplicate timer detection == */
#define NUM_HASH_BUCKETS 1009 /* Prime number close to 1000 */
@ -177,7 +177,7 @@ static void remove_from_ht(grpc_timer* t) {
t->hash_table_next = nullptr;
}
/* If a timer is added to a timer shard (either heap or a list), it cannot
/* If a timer is added to a timer shard (either heap or a list), it must
* be pending. A timer is added to hash table only-if it is added to the
* timer shard.
* Therefore, if timer->pending is false, it cannot be in hash table */
@ -489,7 +489,7 @@ static void timer_cancel(grpc_timer* timer) {
'queue_deadline_cap') into into shard->heap.
Returns 'true' if shard->heap has atleast ONE element
REQUIRES: shard->mu locked */
static int refill_heap(timer_shard* shard, grpc_millis now) {
static bool refill_heap(timer_shard* shard, grpc_millis now) {
/* Compute the new queue window width and bound by the limits: */
double computed_deadline_delta =
grpc_time_averaged_stats_update_average(&shard->stats) *

@ -95,7 +95,7 @@ void grpc_timer_heap_init(grpc_timer_heap* heap) {
void grpc_timer_heap_destroy(grpc_timer_heap* heap) { gpr_free(heap->timers); }
int grpc_timer_heap_add(grpc_timer_heap* heap, grpc_timer* timer) {
bool grpc_timer_heap_add(grpc_timer_heap* heap, grpc_timer* timer) {
if (heap->timer_count == heap->timer_capacity) {
heap->timer_capacity =
GPR_MAX(heap->timer_capacity + 1, heap->timer_capacity * 3 / 2);
@ -122,7 +122,7 @@ void grpc_timer_heap_remove(grpc_timer_heap* heap, grpc_timer* timer) {
note_changed_priority(heap, heap->timers[i]);
}
int grpc_timer_heap_is_empty(grpc_timer_heap* heap) {
bool grpc_timer_heap_is_empty(grpc_timer_heap* heap) {
return heap->timer_count == 0;
}

@ -29,8 +29,8 @@ typedef struct {
uint32_t timer_capacity;
} grpc_timer_heap;
/* return 1 if the new timer is the first timer in the heap */
int grpc_timer_heap_add(grpc_timer_heap* heap, grpc_timer* timer);
/* return true if the new timer is the first timer in the heap */
bool grpc_timer_heap_add(grpc_timer_heap* heap, grpc_timer* timer);
void grpc_timer_heap_init(grpc_timer_heap* heap);
void grpc_timer_heap_destroy(grpc_timer_heap* heap);
@ -39,6 +39,6 @@ void grpc_timer_heap_remove(grpc_timer_heap* heap, grpc_timer* timer);
grpc_timer* grpc_timer_heap_top(grpc_timer_heap* heap);
void grpc_timer_heap_pop(grpc_timer_heap* heap);
int grpc_timer_heap_is_empty(grpc_timer_heap* heap);
bool grpc_timer_heap_is_empty(grpc_timer_heap* heap);
#endif /* GRPC_CORE_LIB_IOMGR_TIMER_HEAP_H */

@ -100,8 +100,7 @@ static void start_timer_thread_and_unlock(void) {
void grpc_timer_manager_tick() {
grpc_core::ExecCtx exec_ctx;
grpc_millis next = GRPC_MILLIS_INF_FUTURE;
grpc_timer_check(&next);
grpc_timer_check(nullptr);
}
static void run_some_timers() {
@ -110,9 +109,12 @@ static void run_some_timers() {
// remove a waiter from the pool, and start another thread if necessary
--g_waiter_count;
if (g_waiter_count == 0 && g_threaded) {
// The number of timer threads is always increasing until all the threads
// are stopped. In rare cases, if a large number of timers fire
// simultaneously, we may end up using a large number of threads.
start_timer_thread_and_unlock();
} else {
// if there's no thread waiting with a timeout, kick an existing
// if there's no thread waiting with a timeout, kick an existing untimed
// waiter so that the next deadline is not missed
if (!g_has_timed_waiter) {
if (grpc_timer_check_trace.enabled()) {

@ -23,8 +23,8 @@
#include <stdbool.h>
/* Timer Manager tries to keep one thread waiting for the next timeout at all
times */
/* Timer Manager tries to keep only one thread waiting for the next timeout at
all times, and thus effectively preventing the thundering herd problem. */
void grpc_timer_manager_init(void);
void grpc_timer_manager_shutdown(void);

Loading…
Cancel
Save