Skip to content

Commit c2bf90c

Browse files
Merge pull request #753 from ava-labs/improve-rpcchainvm-caching
Basic `rpcchainvm` Caching + metercacher
2 parents bd482b7 + 4617754 commit c2bf90c

File tree

7 files changed

+345
-118
lines changed

7 files changed

+345
-118
lines changed

cache/lru_cache_test.go

Lines changed: 4 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -10,124 +10,15 @@ import (
1010
)
1111

1212
func TestLRU(t *testing.T) {
13-
cache := LRU{Size: 1}
13+
cache := &LRU{Size: 1}
1414

15-
id1 := ids.ID{1}
16-
if _, found := cache.Get(id1); found {
17-
t.Fatalf("Retrieved value when none exists")
18-
}
19-
20-
expectedValue1 := 1
21-
cache.Put(id1, expectedValue1)
22-
if value, found := cache.Get(id1); !found {
23-
t.Fatalf("Failed to retrieve value when one exists")
24-
} else if value != expectedValue1 {
25-
t.Fatalf("Failed to retrieve correct value when one exists")
26-
}
27-
28-
cache.Put(id1, expectedValue1)
29-
if value, found := cache.Get(id1); !found {
30-
t.Fatalf("Failed to retrieve value when one exists")
31-
} else if value != expectedValue1 {
32-
t.Fatalf("Failed to retrieve correct value when one exists")
33-
}
34-
35-
cache.Put(id1, expectedValue1)
36-
if value, found := cache.Get(id1); !found {
37-
t.Fatalf("Failed to retrieve value when one exists")
38-
} else if value != expectedValue1 {
39-
t.Fatalf("Failed to retrieve correct value when one exists")
40-
}
41-
42-
id2 := ids.ID{2}
43-
44-
expectedValue2 := 2
45-
cache.Put(id2, expectedValue2)
46-
if _, found := cache.Get(id1); found {
47-
t.Fatalf("Retrieved value when none exists")
48-
}
49-
if value, found := cache.Get(id2); !found {
50-
t.Fatalf("Failed to retrieve value when one exists")
51-
} else if value != expectedValue2 {
52-
t.Fatalf("Failed to retrieve correct value when one exists")
53-
}
15+
TestBasic(t, cache)
5416
}
5517

5618
func TestLRUEviction(t *testing.T) {
57-
cache := LRU{Size: 2}
58-
59-
id1 := ids.ID{1}
60-
id2 := ids.ID{2}
61-
id3 := ids.ID{3}
62-
63-
cache.Put(id1, 1)
64-
cache.Put(id2, 2)
65-
66-
if val, found := cache.Get(id1); !found {
67-
t.Fatalf("Failed to retrieve value when one exists")
68-
} else if val != 1 {
69-
t.Fatalf("Retrieved wrong value")
70-
} else if val, found := cache.Get(id2); !found {
71-
t.Fatalf("Failed to retrieve value when one exists")
72-
} else if val != 2 {
73-
t.Fatalf("Retrieved wrong value")
74-
} else if _, found := cache.Get(id3); found {
75-
t.Fatalf("Retrieve value when none exists")
76-
}
77-
78-
cache.Put(id3, 3)
79-
80-
if _, found := cache.Get(id1); found {
81-
t.Fatalf("Retrieve value when none exists")
82-
} else if val, found := cache.Get(id2); !found {
83-
t.Fatalf("Failed to retrieve value when one exists")
84-
} else if val != 2 {
85-
t.Fatalf("Retrieved wrong value")
86-
} else if val, found := cache.Get(id3); !found {
87-
t.Fatalf("Failed to retrieve value when one exists")
88-
} else if val != 3 {
89-
t.Fatalf("Retrieved wrong value")
90-
}
91-
92-
cache.Get(id2)
93-
cache.Put(id1, 1)
94-
95-
if val, found := cache.Get(id1); !found {
96-
t.Fatalf("Failed to retrieve value when one exists")
97-
} else if val != 1 {
98-
t.Fatalf("Retrieved wrong value")
99-
} else if val, found := cache.Get(id2); !found {
100-
t.Fatalf("Failed to retrieve value when one exists")
101-
} else if val != 2 {
102-
t.Fatalf("Retrieved wrong value")
103-
} else if _, found := cache.Get(id3); found {
104-
t.Fatalf("Retrieved value when none exists")
105-
}
106-
107-
cache.Evict(id2)
108-
cache.Put(id3, 3)
109-
110-
if val, found := cache.Get(id1); !found {
111-
t.Fatalf("Failed to retrieve value when one exists")
112-
} else if val != 1 {
113-
t.Fatalf("Retrieved wrong value")
114-
} else if _, found := cache.Get(id2); found {
115-
t.Fatalf("Retrieved value when none exists")
116-
} else if val, found := cache.Get(id3); !found {
117-
t.Fatalf("Failed to retrieve value when one exists")
118-
} else if val != 3 {
119-
t.Fatalf("Retrieved wrong value")
120-
}
121-
122-
cache.Flush()
19+
cache := &LRU{Size: 2}
12320

124-
if _, found := cache.Get(id1); found {
125-
t.Fatalf("Retrieved value when none exists")
126-
} else if _, found := cache.Get(id2); found {
127-
t.Fatalf("Retrieved value when none exists")
128-
} else if _, found := cache.Get(id3); found {
129-
t.Fatalf("Retrieved value when none exists")
130-
}
21+
TestEviction(t, cache)
13122
}
13223

13324
func TestLRUResize(t *testing.T) {

cache/metercacher/cache.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
2+
// See the file LICENSE for licensing terms.
3+
4+
package metercacher
5+
6+
import (
7+
"github.com/prometheus/client_golang/prometheus"
8+
9+
"github.com/ava-labs/avalanchego/cache"
10+
"github.com/ava-labs/avalanchego/ids"
11+
"github.com/ava-labs/avalanchego/utils/timer"
12+
)
13+
14+
type Cache struct {
15+
metrics
16+
cache cache.Cacher
17+
clock timer.Clock
18+
}
19+
20+
func New(
21+
namespace string,
22+
registerer prometheus.Registerer,
23+
cache cache.Cacher,
24+
) (cache.Cacher, error) {
25+
meterCache := &Cache{cache: cache}
26+
return meterCache, meterCache.metrics.Initialize(namespace, registerer)
27+
}
28+
29+
func (c *Cache) Put(key ids.ID, value interface{}) {
30+
start := c.clock.Time()
31+
c.cache.Put(key, value)
32+
end := c.clock.Time()
33+
c.put.Observe(float64(end.Sub(start)))
34+
}
35+
36+
func (c *Cache) Get(key ids.ID) (interface{}, bool) {
37+
start := c.clock.Time()
38+
value, has := c.cache.Get(key)
39+
end := c.clock.Time()
40+
c.get.Observe(float64(end.Sub(start)))
41+
if has {
42+
c.hit.Inc()
43+
} else {
44+
c.miss.Inc()
45+
}
46+
47+
return value, has
48+
}
49+
50+
func (c *Cache) Evict(key ids.ID) {
51+
start := c.clock.Time()
52+
c.cache.Evict(key)
53+
end := c.clock.Time()
54+
c.evict.Observe(float64(end.Sub(start)))
55+
}
56+
57+
func (c *Cache) Flush() {
58+
start := c.clock.Time()
59+
c.cache.Flush()
60+
end := c.clock.Time()
61+
c.flush.Observe(float64(end.Sub(start)))
62+
}

cache/metercacher/cache_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package metercacher
2+
3+
import (
4+
"testing"
5+
6+
"github.com/prometheus/client_golang/prometheus"
7+
8+
"github.com/ava-labs/avalanchego/cache"
9+
)
10+
11+
func TestInterface(t *testing.T) {
12+
for _, test := range cache.CacherTests {
13+
cache := &cache.LRU{Size: test.Size}
14+
c, err := New("", prometheus.NewRegistry(), cache)
15+
if err != nil {
16+
t.Fatal(err)
17+
}
18+
19+
test.Func(t, c)
20+
}
21+
}

cache/metercacher/metrics.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
2+
// See the file LICENSE for licensing terms.
3+
4+
package metercacher
5+
6+
import (
7+
"fmt"
8+
9+
"github.com/prometheus/client_golang/prometheus"
10+
11+
"github.com/ava-labs/avalanchego/utils/timer"
12+
"github.com/ava-labs/avalanchego/utils/wrappers"
13+
)
14+
15+
func newHistogramMetric(namespace, name string) prometheus.Histogram {
16+
return prometheus.NewHistogram(prometheus.HistogramOpts{
17+
Namespace: namespace,
18+
Name: name,
19+
Help: fmt.Sprintf("Latency of a %s call in nanoseconds", name),
20+
Buckets: timer.NanosecondsBuckets,
21+
})
22+
}
23+
24+
func newCounterMetric(namespace, name string) prometheus.Counter {
25+
return prometheus.NewCounter(prometheus.CounterOpts{
26+
Namespace: namespace,
27+
Name: name,
28+
Help: fmt.Sprintf("# of times a %s occurred", name),
29+
})
30+
}
31+
32+
type metrics struct {
33+
get,
34+
put,
35+
evict,
36+
flush prometheus.Histogram
37+
38+
hit,
39+
miss prometheus.Counter
40+
}
41+
42+
func (m *metrics) Initialize(
43+
namespace string,
44+
registerer prometheus.Registerer,
45+
) error {
46+
m.get = newHistogramMetric(namespace, "get")
47+
m.put = newHistogramMetric(namespace, "put")
48+
m.evict = newHistogramMetric(namespace, "evict")
49+
m.flush = newHistogramMetric(namespace, "flush")
50+
m.hit = newCounterMetric(namespace, "hit")
51+
m.miss = newCounterMetric(namespace, "miss")
52+
53+
errs := wrappers.Errs{}
54+
errs.Add(
55+
registerer.Register(m.get),
56+
registerer.Register(m.put),
57+
registerer.Register(m.evict),
58+
registerer.Register(m.flush),
59+
registerer.Register(m.hit),
60+
registerer.Register(m.miss),
61+
)
62+
return errs.Err
63+
}

0 commit comments

Comments
 (0)