github.com/maypok86/otter@v1.2.1/stats.go (about)

     1  // Copyright (c) 2024 Alexey Mayshev. All rights reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package otter
    16  
    17  import (
    18  	"math"
    19  
    20  	"github.com/maypok86/otter/internal/stats"
    21  )
    22  
    23  // Stats is a statistics snapshot.
    24  type Stats struct {
    25  	hits         int64
    26  	misses       int64
    27  	rejectedSets int64
    28  	evictedCount int64
    29  	evictedCost  int64
    30  }
    31  
    32  func newStats(s *stats.Stats) Stats {
    33  	return Stats{
    34  		hits:         negativeToMax(s.Hits()),
    35  		misses:       negativeToMax(s.Misses()),
    36  		rejectedSets: negativeToMax(s.RejectedSets()),
    37  		evictedCount: negativeToMax(s.EvictedCount()),
    38  		evictedCost:  negativeToMax(s.EvictedCost()),
    39  	}
    40  }
    41  
    42  // Hits returns the number of cache hits.
    43  func (s Stats) Hits() int64 {
    44  	return s.hits
    45  }
    46  
    47  // Misses returns the number of cache misses.
    48  func (s Stats) Misses() int64 {
    49  	return s.misses
    50  }
    51  
    52  // Ratio returns the cache hit ratio.
    53  func (s Stats) Ratio() float64 {
    54  	requests := checkedAdd(s.hits, s.misses)
    55  	if requests == 0 {
    56  		return 0.0
    57  	}
    58  	return float64(s.hits) / float64(requests)
    59  }
    60  
    61  // RejectedSets returns the number of rejected sets.
    62  func (s Stats) RejectedSets() int64 {
    63  	return s.rejectedSets
    64  }
    65  
    66  // EvictedCount returns the number of evicted entries.
    67  func (s Stats) EvictedCount() int64 {
    68  	return s.evictedCount
    69  }
    70  
    71  // EvictedCost returns the sum of costs of evicted entries.
    72  func (s Stats) EvictedCost() int64 {
    73  	return s.evictedCost
    74  }
    75  
    76  func checkedAdd(a, b int64) int64 {
    77  	naiveSum := a + b
    78  	if (a^b) < 0 || (a^naiveSum) >= 0 {
    79  		// If a and b have different signs or a has the same sign as the result then there was no overflow, return.
    80  		return naiveSum
    81  	}
    82  	// we did over/under flow, if the sign is negative we should return math.MaxInt64 otherwise math.MinInt64.
    83  	return math.MaxInt64 + ((naiveSum >> 63) ^ 1)
    84  }
    85  
    86  func negativeToMax(v int64) int64 {
    87  	if v < 0 {
    88  		return math.MaxInt64
    89  	}
    90  
    91  	return v
    92  }