@@ -103,23 +103,73 @@ func (m *CostAwareMemoryIndex) MaxCost() int64 {
103103
104104// CostPodCache wraps a sync.Map of PodEntry and provides cost calculation for memory usage estimation.
105105type CostPodCache struct {
106- cache sync.Map // map[PodEntry]struct{}
106+ cache sync.Map // map[string]*PodEntry (key: "podID@tier")
107107 // size tracks the number of entries in cache for O(1) Len().
108108 size atomic.Int64
109109}
110110
111- // Add adds a PodEntry to the cache.
111+ // Add adds or updates a PodEntry in the cache, merging StoredGroups if the entry exists .
112112func (c * CostPodCache ) Add (entry PodEntry ) {
113- if _ , loaded := c .cache .LoadOrStore (entry , struct {}{}); ! loaded {
113+ cacheKey := podCacheKey (entry .PodIdentifier , entry .DeviceTier , entry .Speculative )
114+
115+ // Try to load existing entry
116+ if existingVal , loaded := c .cache .Load (cacheKey ); loaded {
117+ if existingEntry , ok := existingVal .(* PodEntry ); ok {
118+ // Merge StoredGroups
119+ existingEntry .StoredGroups = mergeGroupsUnique (existingEntry .StoredGroups , entry .StoredGroups )
120+ // Store updated entry
121+ c .cache .Store (cacheKey , existingEntry )
122+ }
123+ } else {
124+ // Create new entry
125+ newEntry := & PodEntry {
126+ PodIdentifier : entry .PodIdentifier ,
127+ DeviceTier : entry .DeviceTier ,
128+ Speculative : entry .Speculative ,
129+ StoredGroups : mergeGroupsUnique (nil , entry .StoredGroups ),
130+ }
131+ c .cache .Store (cacheKey , newEntry )
114132 c .size .Add (1 )
115133 }
116134}
117135
118- // Delete removes a PodEntry from the cache.
136+ // Delete removes a PodEntry from the cache entirely .
119137func (c * CostPodCache ) Delete (entry PodEntry ) {
120- if _ , loaded := c .cache .LoadAndDelete (entry ); loaded {
138+ cacheKey := podCacheKey (entry .PodIdentifier , entry .DeviceTier , entry .Speculative )
139+ if _ , loaded := c .cache .LoadAndDelete (cacheKey ); loaded {
140+ c .size .Add (- 1 )
141+ }
142+ }
143+
144+ // RemoveGroups removes specified groups from a PodEntry's StoredGroups.
145+ // If no groups remain, the entry is deleted.
146+ func (c * CostPodCache ) RemoveGroups (entry PodEntry ) bool {
147+ cacheKey := podCacheKey (entry .PodIdentifier , entry .DeviceTier , entry .Speculative )
148+
149+ existingVal , loaded := c .cache .Load (cacheKey )
150+ if ! loaded {
151+ return false
152+ }
153+
154+ existingEntry , ok := existingVal .(* PodEntry )
155+ if ! ok {
156+ return false
157+ }
158+
159+ // Remove specified groups
160+ updatedGroups := removeGroups (existingEntry .StoredGroups , entry .StoredGroups )
161+
162+ if len (updatedGroups ) == 0 {
163+ // No groups left, delete the entry
164+ c .cache .Delete (cacheKey )
121165 c .size .Add (- 1 )
166+ return true
122167 }
168+
169+ // Update with remaining groups
170+ existingEntry .StoredGroups = updatedGroups
171+ c .cache .Store (cacheKey , existingEntry )
172+ return false
123173}
124174
125175// Len returns the number of entries in the cache.
@@ -141,16 +191,22 @@ func (c *CostPodCache) CalculateByteSize(keyStr string) int64 {
141191
142192 // Count entries and calculate their size
143193 c .cache .Range (func (key , value interface {}) bool {
144- entry , ok := key .(PodEntry )
145- if ! ok {
194+ // key is now a string, value is *PodEntry
195+ keyStr , okKey := key .(string )
196+ entry , okEntry := value .(* PodEntry )
197+ if ! okKey || ! okEntry {
146198 return true
147199 }
148200
149201 entryCount ++
150- totalBytes += int64 (len (entry .PodIdentifier )) // PodIdentifier string content
151- totalBytes += int64 (len (entry .DeviceTier )) // DeviceTier string content
152- totalBytes += 32 // string headers (16 bytes each for 2 strings)
153- totalBytes += 8 // struct padding/alignment
202+ totalBytes += int64 (len (keyStr )) // cache key string
203+ totalBytes += int64 (len (entry .PodIdentifier )) // PodIdentifier string content
204+ totalBytes += int64 (len (entry .DeviceTier )) // DeviceTier string content
205+ totalBytes += int64 (len (entry .StoredGroups ) * 8 ) // StoredGroups slice (8 bytes per int)
206+ totalBytes += 32 // string headers (16 bytes each for 2 strings)
207+ totalBytes += 24 // slice header for StoredGroups
208+ totalBytes += 8 // pointer to PodEntry
209+ totalBytes += 8 // struct padding/alignment
154210 return true
155211 })
156212
@@ -234,17 +290,17 @@ func (m *CostAwareMemoryIndex) Lookup(ctx context.Context, requestKeys []BlockHa
234290 if podIdentifierSet .Len () == 0 {
235291 // If no pod identifiers are provided, return all pods
236292 pods .cache .Range (func (k , value interface {}) bool {
237- if pod , ok := k .( PodEntry ); ok {
238- podsPerKey [key ] = append (podsPerKey [key ], pod )
293+ if pod , ok := value .( * PodEntry ); ok {
294+ podsPerKey [key ] = append (podsPerKey [key ], * pod )
239295 }
240296 return true
241297 })
242298 } else {
243299 // Filter pods based on the provided pod identifiers
244300 pods .cache .Range (func (k , value interface {}) bool {
245- if pod , ok := k .( PodEntry ); ok {
301+ if pod , ok := value .( * PodEntry ); ok {
246302 if podIdentifierSet .Has (pod .PodIdentifier ) {
247- podsPerKey [key ] = append (podsPerKey [key ], pod )
303+ podsPerKey [key ] = append (podsPerKey [key ], * pod )
248304 }
249305 }
250306 return true
@@ -307,7 +363,8 @@ func (m *CostAwareMemoryIndex) Evict(ctx context.Context, key BlockHash, keyType
307363 podCacheLenBefore := podCache .Len ()
308364
309365 for _ , entry := range entries {
310- podCache .Delete (entry )
366+ // Remove groups from the entry; if no groups remain, the entry is deleted
367+ podCache .RemoveGroups (entry )
311368 }
312369
313370 if podCache .Len () == 0 {
0 commit comments