mirror of
https://github.com/MariaDB/server.git
synced 2025-02-02 03:51:50 +01:00
40 lines
2.4 KiB
C
40 lines
2.4 KiB
C
|
#ifndef THREAD_LOCAL_COUNTER_H
|
||
|
#define THREAD_LOCAL_COUNTER_H
|
||
|
|
||
|
// Overview: A partitioned_counter provides a counter that can be incremented and the running sum can be read at any time.
|
||
|
// We assume that increments are frequent, whereas reading is infrequent.
|
||
|
// Implementation hint: Use thread-local storage so each thread increments its own data. The increment does not require a lock or atomic operation.
|
||
|
// Reading the data can be performed by iterating over the thread-local versions, summing them up.
|
||
|
// The data structure also includes a sum for all the threads that have died.
|
||
|
// Use a pthread_key to create the thread-local versions. When a thread finishes, the system calls pthread_key destructor which can add that thread's copy
|
||
|
// into the sum_of_dead counter.
|
||
|
// Rationale: For statistics such as are found in engine status, we need a counter that requires no cache misses to increment. We've seen significant
|
||
|
// performance speedups by removing certain counters. Rather than removing those statistics, we would like to just make the counter fast.
|
||
|
// We generally increment the counters frequently, and want to fetch the values infrequently.
|
||
|
// The counters are monotonic.
|
||
|
// The counters can be split into many counters, which can be summed up at the end.
|
||
|
// We don't care if we get slightly out-of-date counter sums when we read the counter. We don't care if there is a race on reading the a counter
|
||
|
// variable and incrementing.
|
||
|
// See tests/test_partitioned_counter.c for some performance measurements.
|
||
|
// Operations:
|
||
|
// create_partitioned_counter Create a counter initialized to zero.
|
||
|
// destroy_partitioned_counter Destroy it.
|
||
|
// increment_partitioned_counter Increment it. This is the frequent operation.
|
||
|
// read_partitioned_counter Get the current value. This is infrequent.
|
||
|
|
||
|
typedef struct partitioned_counter *PARTITIONED_COUNTER;
|
||
|
PARTITIONED_COUNTER create_partitioned_counter(void);
|
||
|
// Effect: Create a counter, initialized to zero.
|
||
|
|
||
|
void destroy_partitioned_counter (PARTITIONED_COUNTER);
|
||
|
// Effect: Destroy the counter. No operations on that counter are permitted after this.
|
||
|
|
||
|
void increment_partitioned_counter (PARTITIONED_COUNTER, unsigned long amount);
|
||
|
// Effect: Increment the counter by amount.
|
||
|
// Requires: No overflows. This is a 64-bit unsigned counter.
|
||
|
|
||
|
unsigned long read_partitioned_counter (PARTITIONED_COUNTER);
|
||
|
// Effect: Return the current value of the counter.
|
||
|
|
||
|
#endif
|