milvus/pkg/util/cache/stats.go
jaime c9d0c157ec
Move some modules from internal to public package (#22572)
Signed-off-by: jaime <yun.zhang@zilliz.com>
2023-04-06 19:14:32 +08:00

144 lines
4.4 KiB
Go

// Licensed to the LF AI & Data foundation under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package cache
import (
"fmt"
"sync/atomic"
"time"
)
// Stats is statistics about performance of a cache.
type Stats struct {
HitCount uint64
MissCount uint64
LoadSuccessCount uint64
LoadErrorCount uint64
TotalLoadTime time.Duration
EvictionCount uint64
}
// RequestCount returns a total of HitCount and MissCount.
func (s *Stats) RequestCount() uint64 {
return s.HitCount + s.MissCount
}
// HitRate returns the ratio of cache requests which were hits.
func (s *Stats) HitRate() float64 {
total := s.RequestCount()
if total == 0 {
return 1.0
}
return float64(s.HitCount) / float64(total)
}
// MissRate returns the ratio of cache requests which were misses.
func (s *Stats) MissRate() float64 {
total := s.RequestCount()
if total == 0 {
return 0.0
}
return float64(s.MissCount) / float64(total)
}
// LoadErrorRate returns the ratio of cache loading attempts which returned errors.
func (s *Stats) LoadErrorRate() float64 {
total := s.LoadSuccessCount + s.LoadErrorCount
if total == 0 {
return 0.0
}
return float64(s.LoadErrorCount) / float64(total)
}
// AverageLoadPenalty returns the average time spent loading new values.
func (s *Stats) AverageLoadPenalty() time.Duration {
total := s.LoadSuccessCount + s.LoadErrorCount
if total == 0 {
return 0.0
}
return s.TotalLoadTime / time.Duration(total)
}
// String returns a string representation of this statistics.
func (s *Stats) String() string {
return fmt.Sprintf("hits: %d, misses: %d, successes: %d, errors: %d, time: %s, evictions: %d",
s.HitCount, s.MissCount, s.LoadSuccessCount, s.LoadErrorCount, s.TotalLoadTime, s.EvictionCount)
}
// StatsCounter accumulates statistics of a cache.
type StatsCounter interface {
// RecordHits records cache hits.
RecordHits(count uint64)
// RecordMisses records cache misses.
RecordMisses(count uint64)
// RecordLoadSuccess records successful load of a new entry.
RecordLoadSuccess(loadTime time.Duration)
// RecordLoadError records failed load of a new entry.
RecordLoadError(loadTime time.Duration)
// RecordEviction records eviction of an entry from the cache.
RecordEviction()
// Snapshot writes snapshot of this counter values to the given Stats pointer.
Snapshot(*Stats)
}
// statsCounter is a simple implementation of StatsCounter.
type statsCounter struct {
Stats
}
// RecordHits increases HitCount atomically.
func (s *statsCounter) RecordHits(count uint64) {
atomic.AddUint64(&s.Stats.HitCount, count)
}
// RecordMisses increases MissCount atomically.
func (s *statsCounter) RecordMisses(count uint64) {
atomic.AddUint64(&s.Stats.MissCount, count)
}
// RecordLoadSuccess increases LoadSuccessCount atomically.
func (s *statsCounter) RecordLoadSuccess(loadTime time.Duration) {
atomic.AddUint64(&s.Stats.LoadSuccessCount, 1)
atomic.AddInt64((*int64)(&s.Stats.TotalLoadTime), int64(loadTime))
}
// RecordLoadError increases LoadErrorCount atomically.
func (s *statsCounter) RecordLoadError(loadTime time.Duration) {
atomic.AddUint64(&s.Stats.LoadErrorCount, 1)
atomic.AddInt64((*int64)(&s.Stats.TotalLoadTime), int64(loadTime))
}
// RecordEviction increases EvictionCount atomically.
func (s *statsCounter) RecordEviction() {
atomic.AddUint64(&s.Stats.EvictionCount, 1)
}
// Snapshot copies current stats to t.
func (s *statsCounter) Snapshot(t *Stats) {
t.HitCount = atomic.LoadUint64(&s.HitCount)
t.MissCount = atomic.LoadUint64(&s.MissCount)
t.LoadSuccessCount = atomic.LoadUint64(&s.LoadSuccessCount)
t.LoadErrorCount = atomic.LoadUint64(&s.LoadErrorCount)
t.TotalLoadTime = time.Duration(atomic.LoadInt64((*int64)(&s.TotalLoadTime)))
t.EvictionCount = atomic.LoadUint64(&s.EvictionCount)
}