Skip to content

Commit

Permalink
add slice cache
Browse files Browse the repository at this point in the history
  • Loading branch information
mazrean committed Feb 25, 2023
1 parent 8099890 commit 8e5e219
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .tool-versions
Original file line number Diff line number Diff line change
@@ -1 +1 @@
golang 1.19rc1
golang 1.20.1
136 changes: 136 additions & 0 deletions cache/sc.go
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,142 @@ func (m *AtomicMap[K, V, T]) LoadFromGob(r io.Reader) error {
return nil
}

type Slice[T any] struct {
s []T
locker sync.RWMutex
indexMetrics prometheus.Histogram
lengthMetrics prometheus.Gauge
}

func NewSlice[T any](name string, init []T, size int) *Slice[T] {
var (
indexMetrics prometheus.Histogram
lengthMetrics prometheus.Gauge
)
if isutools.Enable {
indexMetrics = promauto.NewHistogram(prometheus.HistogramOpts{
Namespace: prometheusNamespace,
Subsystem: prometheusSubsystem,
Name: "index_access",
ConstLabels: prometheus.Labels{
"name": name,
},
Buckets: prometheus.LinearBuckets(0, float64(size)/20, 20),
})

lengthMetrics = promauto.NewGauge(prometheus.GaugeOpts{
Namespace: prometheusNamespace,
Subsystem: prometheusSubsystem,
Name: "length",
ConstLabels: prometheus.Labels{
"name": name,
},
})
}

m := &Slice[T]{
s: init,
locker: sync.RWMutex{},
indexMetrics: indexMetrics,
lengthMetrics: lengthMetrics,
}

cacheMap[name] = m

return m
}

func (s *Slice[T]) Get(i int) (T, bool) {
if s.indexMetrics != nil {
s.indexMetrics.Observe(float64(i))
}

var v T
s.locker.RLock()
if i >= len(s.s) {
s.locker.RUnlock()
return v, false
}

v = s.s[i]
s.locker.RUnlock()

return v, true
}

func (s *Slice[T]) Edit(f func([]T) []T) {
s.locker.Lock()
s.s = f(s.s)
s.locker.Unlock()
}

func (s *Slice[T]) Append(values ...T) {
s.locker.Lock()
s.s = append(s.s, values...)

if s.lengthMetrics != nil {
s.lengthMetrics.Set(float64(len(s.s)))
}
s.locker.Unlock()
}

func (s *Slice[T]) Len() int {
return len(s.s)
}

func (s *Slice[T]) Range(f func(int, T) bool) {
s.locker.RLock()
for i, v := range s.s {
if s.indexMetrics != nil {
s.indexMetrics.Observe(float64(i))
}
if !f(i, v) {
break
}
}
s.locker.RUnlock()
}

func (s *Slice[T]) Purge() {
if s.lengthMetrics != nil {
s.lengthMetrics.Set(0)
}

s.locker.Lock()
s.s = nil
s.locker.Unlock()
}

func (s *Slice[T]) WriteToGob(w io.Writer) error {
s.locker.RLock()
gobSlice := make([]T, 0, len(s.s))
for _, v := range s.s {
gobSlice = append(gobSlice, v)
}
s.locker.RUnlock()

err := gob.NewEncoder(w).Encode(gobSlice)
if err != nil {
return fmt.Errorf("failed to write to gob: %w", err)
}

return nil
}

func (s *Slice[T]) LoadFromGob(r io.Reader) error {
gobSlice := []T{}
err := gob.NewDecoder(r).Decode(&gobSlice)
if err != nil {
return fmt.Errorf("failed to load from gob: %w", err)
}

s.locker.Lock()
s.s = gobSlice
s.locker.Unlock()

return nil
}

func AllPurge() {
for _, cache := range cacheMap {
cache.Purge()
Expand Down

0 comments on commit 8e5e219

Please sign in to comment.