Fast, persistent, atomically incrementing, cross-process counters.
Copyright (C) 2011, 2015 Asher Blum; http://wildsparx.com/fastcounters/
- Can be used by multiple related or unrelated processes.
- Can be used by multiple threads. No need to lock.
- Persistent, but lazily - if you pull the power cord, data is lost.
- Command line tool for creating and inspecting the counter file.
- Counter file contains multiple named counters.
Approx 385 million increments per second. Measured with:
- 4 processes
- 10M increments each
- 4 core i7 CPU
- 2.67GHz
Linux, Intel, GCC.
Fastcounters uses a memory mapped file and increments the counters with the atomic xaddl instruction; the code is taken from the linux kernel.
GPL, since it uses code from the linux kernel.
Create a file with four anonymous counters like this:
fastcounters -n4 counters.dat
(They will be named C0 thru C3)
Or create a file with three named counters like this:
fastcounters -n cats,dogs,snakes counters.dat
In a C program, you can increment a counter like this:
int res;
if(fcntrs_incr(&fc, 0, &res)) {
// handle error
}
Note:
- fc is a fastcounters handle already opened.
- This increments the first (position 0) counter in the file.
- res now contains the new counter value.
There are three ways of addressing counters:
Shown in the example above.
Given a counters file, you can generate a C fragment with:
fastcounters -poh counters.dat
This will produce output like:
#define COUNTER_cats 0
#define COUNTER_dogs 1
#define COUNTER_snakes 2
You can use these defined constants to access the counters.
You can dynamically resolve counter names to IDs:
int cnt_id;
if(fcntrs_resolve_name(fc, "dogs", &cnt_id)) {
// handle error
}
Since this lookup is signficantly slower than incrementing a counter, the result should be cached. One way to do this is with static variables:
static int cnt_id = -1;
if(cnt_id == -1) { // first time
if(fcntrs_resolve_name(fc, "dogs", &cnt_id)) {
...