@@ -11,31 +11,29 @@ type CacheEntry struct {
11
11
}
12
12
13
13
type Cache struct {
14
- sync.Mutex
14
+ sync.RWMutex
15
15
entries map [string ]CacheEntry
16
16
globalTTL time.Duration
17
- ticker * time.Ticker
18
17
}
19
18
20
19
func New (globalTTL time.Duration ) * Cache {
21
20
cache := & Cache {
22
21
entries : make (map [string ]CacheEntry ),
23
22
globalTTL : globalTTL ,
24
- ticker : time .NewTicker (globalTTL / 2 ),
25
23
}
26
24
27
- // Start the cache.
28
- cache .Start ( )
25
+ // Start the cache cleanup .
26
+ go cache .cleanupRoutine ( globalTTL )
29
27
return cache
30
28
}
31
29
32
- func (c * Cache ) Start ( ) {
33
- go func () {
34
- for {
35
- <- c . ticker . C
36
- c . CleanExpiredEntries ()
37
- }
38
- }()
30
+ func (c * Cache ) cleanupRoutine ( globalTTL time. Duration ) {
31
+ ticker := time . NewTicker ( globalTTL / 2 )
32
+ defer ticker . Stop ()
33
+
34
+ for range ticker . C {
35
+ c . CleanExpiredEntries ()
36
+ }
39
37
}
40
38
41
39
func (c * Cache ) Set (key string , value []byte , ttl time.Duration ) {
@@ -55,8 +53,8 @@ func (c *Cache) Set(key string, value []byte, ttl time.Duration) {
55
53
}
56
54
57
55
func (c * Cache ) Get (key string ) ([]byte , bool ) {
58
- c .Lock ()
59
- defer c .Unlock ()
56
+ c .RLock ()
57
+ defer c .RUnlock ()
60
58
61
59
entry , ok := c .entries [key ]
62
60
if ! ok || entry .ExpiresAt .Before (time .Now ()) {
@@ -75,13 +73,20 @@ func (c *Cache) Delete(key string) {
75
73
76
74
func (c * Cache ) CleanExpiredEntries () {
77
75
now := time .Now ()
76
+ toDelete := make ([]string , 0 )
78
77
79
- c .Lock ()
80
- defer c .Unlock ()
81
-
78
+ c .RLock ()
82
79
for key , entry := range c .entries {
83
80
if entry .ExpiresAt .Before (now ) {
84
- delete ( c . entries , key )
81
+ toDelete = append ( toDelete , key )
85
82
}
86
83
}
84
+ c .RUnlock ()
85
+
86
+ // Separate the deletion to its own critical section to reduce lock contention.
87
+ c .Lock ()
88
+ for _ , key := range toDelete {
89
+ delete (c .entries , key )
90
+ }
91
+ c .Unlock ()
87
92
}
0 commit comments