GuestNo new alerts

Counters and Atomics: DefaultViewCounter

- Articles64
 
My analytics are likely a hundred to a thousand times faster than the competition, particularly for gathering aggregate data as opposed to data on one specific request among many which is computationally expensive by nature.

I do have to note that It's really hard to tell without a very precise micro-benchmark however and is mostly an estimate, however, it's a fairly sound one as many systems rely on firing off a query for every request every-time they want to say... Log a view somewhere or track something else.

Gosora on the other-hand does the atomic equivalent of i++ and then inserts data it's accumulated over a period of time once every second or every fifteen minutes.

But, what do we do exactly to achieve this? We know that I usually give i++ as an example to help illustrate how it works, but is atomics really always that simple? I would have to say that it both is and isn't.

https://github.com/Azareal/Gosora/blob/master/common/counters/requests.go#L15

This is DefaultViewCounter, which you may know as the request counter or simply the view counter (although, it includes everything served by Gosora including CSS files, API calls, etc.)

DefaultViewCounter is a fairly simple 37 line function which is divided into the following functions:

An initialiser to create an instance of it, Tick which runs once every fifteen minutes.

Bump which is called in the router every time a new request comes in and increments the counter.

The private function insertChunk which is invoked by Tick to add an entry to the database.

The initialiser, NewDefaultViewCounter is fairly simple. It setups a prepare statement, sets up a scheduled task and sends any errors which popped up during the process up to the caller.

Tick is where much of the magic happens, but it's also a fairly simple function. There are two buckets, which are essentially counters and they take turns as the main counter every cycle when the tick fires.

The reason for this is that Tick operates by getting the current count from the current counter, and then, it deducts that exact amount from it, and then, any overflow from perhaps a request hitting at that instant will overflow to the next cycle and get counted as part of the total for that cycle.

The current count which it does manage to get is inserted into the database for the administrator to look at in their analytics panel.

A few other counters use similar principles, although some more complex ones which can't simply be done with a known number of slots in an array may rely on things like mutexes and sharding which I'll get to later.