@@ -17,20 +17,9 @@ import (
17
17
18
18
"github.com/cockroachdb/pebble/internal/base"
19
19
"github.com/cockroachdb/pebble/internal/invariants"
20
+ "github.com/cockroachdb/pebble/internal/metricsutil"
20
21
)
21
22
22
- // Metrics holds metrics for the cache.
23
- type Metrics struct {
24
- // The number of bytes inuse by the cache.
25
- Size int64
26
- // The count of objects (blocks or tables) in the cache.
27
- Count int64
28
- // The number of cache hits.
29
- Hits int64
30
- // The number of cache misses.
31
- Misses int64
32
- }
33
-
34
23
// Cache implements Pebble's sharded block cache. The Clock-PRO algorithm is
35
24
// used for page replacement
36
25
// (http://static.usenix.org/event/usenix05/tech/general/full_papers/jiang/jiang_html/html.html). In
@@ -78,6 +67,8 @@ type Cache struct {
78
67
idAlloc atomic.Uint64
79
68
shards []shard
80
69
70
+ metricsWindow * metricsutil.Window [HitsAndMisses ]
71
+
81
72
// Traces recorded by Cache.trace. Used for debugging.
82
73
tr struct {
83
74
sync.Mutex
@@ -136,6 +127,8 @@ func NewWithShards(size int64, shards int) *Cache {
136
127
for i := range c .shards {
137
128
c .shards [i ].init (size / int64 (len (c .shards )))
138
129
}
130
+ c .metricsWindow = metricsutil.NewWindow [HitsAndMisses ](c .hitsAndMisses )
131
+ c .metricsWindow .Start ()
139
132
140
133
// Note: this is a no-op if invariants are disabled or race is enabled.
141
134
invariants .SetFinalizer (c , func (c * Cache ) {
@@ -171,10 +164,19 @@ func (c *Cache) Unref() {
171
164
case v < 0 :
172
165
panic (fmt .Sprintf ("pebble: inconsistent reference count: %d" , v ))
173
166
case v == 0 :
174
- for i := range c .shards {
175
- c .shards [i ].Free ()
176
- }
167
+ c .destroy ()
168
+ }
169
+ }
170
+
171
+ func (c * Cache ) destroy () {
172
+ if c .metricsWindow != nil {
173
+ c .metricsWindow .Stop ()
174
+ c .metricsWindow = nil
175
+ }
176
+ for i := range c .shards {
177
+ c .shards [i ].Free ()
177
178
}
179
+ c .shards = nil
178
180
}
179
181
180
182
func (c * Cache ) NewHandle () * Handle {
@@ -207,21 +209,6 @@ func (c *Cache) Reserve(n int) func() {
207
209
}
208
210
}
209
211
210
- // Metrics returns the metrics for the cache.
211
- func (c * Cache ) Metrics () Metrics {
212
- var m Metrics
213
- for i := range c .shards {
214
- s := & c .shards [i ]
215
- s .mu .RLock ()
216
- m .Count += int64 (s .blocks .Len ())
217
- m .Size += s .sizeHot + s .sizeCold
218
- s .mu .RUnlock ()
219
- m .Hits += s .hits .Load ()
220
- m .Misses += s .misses .Load ()
221
- }
222
- return m
223
- }
224
-
225
212
// MaxSize returns the max size of the cache.
226
213
func (c * Cache ) MaxSize () int64 {
227
214
return c .maxSize
@@ -262,16 +249,16 @@ func (c *Handle) Cache() *Cache {
262
249
// Peek retrieves the cache value for the specified file and offset, returning
263
250
// nil if no value is present. Peek does not affect the state of the cache (it
264
251
// does not "count" as an access as far as the cache replacement is concerned).
265
- func (c * Handle ) Peek (fileNum base.DiskFileNum , offset uint64 ) * Value {
252
+ func (c * Handle ) Peek (fileNum base.DiskFileNum , offset uint64 , category Category ) * Value {
266
253
k := makeKey (c .id , fileNum , offset )
267
- return c .cache .getShard (k ).get (k , true /* peekOnly */ )
254
+ return c .cache .getShard (k ).get (k , category , true /* peekOnly */ )
268
255
}
269
256
270
257
// Get retrieves the cache value for the specified file and offset, returning
271
258
// nil if no value is present.
272
- func (c * Handle ) Get (fileNum base.DiskFileNum , offset uint64 ) * Value {
259
+ func (c * Handle ) Get (fileNum base.DiskFileNum , offset uint64 , category Category ) * Value {
273
260
k := makeKey (c .id , fileNum , offset )
274
- return c .cache .getShard (k ).get (k , false /* peekOnly */ )
261
+ return c .cache .getShard (k ).get (k , category , false /* peekOnly */ )
275
262
}
276
263
277
264
// GetWithReadHandle retrieves the cache value for the specified handleID, fileNum
@@ -298,7 +285,7 @@ func (c *Handle) Get(fileNum base.DiskFileNum, offset uint64) *Value {
298
285
// While waiting, someone else may successfully read the value, which results
299
286
// in a valid Handle being returned. This is a case where cacheHit=false.
300
287
func (c * Handle ) GetWithReadHandle (
301
- ctx context.Context , fileNum base.DiskFileNum , offset uint64 ,
288
+ ctx context.Context , fileNum base.DiskFileNum , offset uint64 , category Category ,
302
289
) (
303
290
cv * Value ,
304
291
rh ReadHandle ,
@@ -308,7 +295,7 @@ func (c *Handle) GetWithReadHandle(
308
295
err error ,
309
296
) {
310
297
k := makeKey (c .id , fileNum , offset )
311
- cv , re := c .cache .getShard (k ).getWithReadEntry (k )
298
+ cv , re := c .cache .getShard (k ).getWithReadEntry (k , category )
312
299
if cv != nil {
313
300
return cv , ReadHandle {}, 0 , 0 , true , nil
314
301
}
0 commit comments