-
|
Hi Thank you again for developing otter! Sorry, if this looks too trivial of a question, but I have some concerns with regards to otters architecture for the purpose of keeping counters (concerns how the architecture dictates the choice of APIs, not the concerns about architecture "problems"). Let's imagine I have a whatever-typed key (e.g. integer) and an
|
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
|
Hello,
Perhaps this will help. The company I work for uses a push-based metrics collector (Graphite), and we used to frequently have problems with the speed of sending counters (counters are updated very often, and trying to send data over the network every time is too expensive). In the end, we decided to build an aggregator for these counters that would update them locally and periodically send them to the server. How can something like this be implemented? A map + mutex seems like bad solution because a counter is created only once (on first use), and all subsequent operations with it are reads. You could use sync.Map, but it has problems with constant, meaningless allocations. Otter allows you to make such an aggregator faster and without additional allocations. For example, type Aggregator struct {
counters otter.Cache[string, *int64]
// counters sync.Map
}
// ...
func (a *Aggregator) Add(key string, value int64) {
// create
counter, _ := a.counters.ComputeIfAbsent(key, func() (newValue *int64, cancel bool) {
return new(int64), false
})
atomic.AddInt64(counter, value)
}
// Alternative implementation with sync.Map (commented out):
// func (a *Aggregator) Add(key string, value int64) {
// counter, _ := a.counters.LoadOrStore(key, new(int64))
// atomic.AddInt64(counter.(*int64), value)
// } |
Beta Was this translation helpful? Give feedback.
Hello,