@@ -175,7 +175,7 @@ func (g *Graph) deleteVertex_locked(vertexType vertexType, namespace, name strin
175
175
176
176
// find existing neighbors with a single edge (meaning we are their only neighbor)
177
177
neighborsToRemove := []graph.Node {}
178
- neighborsToRecompute := []graph.Node {}
178
+ edgesToRemoveFromIndexes := []graph.Edge {}
179
179
g .graph .VisitFrom (vertex , func (neighbor graph.Node ) bool {
180
180
// this downstream neighbor has only one edge (which must be from us), so remove them as well
181
181
if g .graph .Degree (neighbor ) == 1 {
@@ -188,8 +188,8 @@ func (g *Graph) deleteVertex_locked(vertexType vertexType, namespace, name strin
188
188
// this upstream neighbor has only one edge (which must be to us), so remove them as well
189
189
neighborsToRemove = append (neighborsToRemove , neighbor )
190
190
} else {
191
- // recompute the destination edge index on this neighbor
192
- neighborsToRecompute = append (neighborsToRecompute , neighbor )
191
+ // decrement the destination edge index on this neighbor if the edge between us was a destination edge
192
+ edgesToRemoveFromIndexes = append (edgesToRemoveFromIndexes , g . graph . EdgeBetween ( vertex , neighbor ) )
193
193
}
194
194
return true
195
195
})
@@ -202,9 +202,9 @@ func (g *Graph) deleteVertex_locked(vertexType vertexType, namespace, name strin
202
202
g .removeVertex_locked (neighbor .(* namedVertex ))
203
203
}
204
204
205
- // recompute destination indexes for neighbors that dropped outbound edges
206
- for _ , neighbor := range neighborsToRecompute {
207
- g .recomputeDestinationIndex_locked ( neighbor )
205
+ // remove edges from destination indexes for neighbors that dropped outbound edges
206
+ for _ , edge := range edgesToRemoveFromIndexes {
207
+ g .removeEdgeFromDestinationIndex_locked ( edge )
208
208
}
209
209
}
210
210
@@ -220,19 +220,17 @@ func (g *Graph) deleteEdges_locked(fromType, toType vertexType, toNamespace, toN
220
220
221
221
// delete all edges between vertices of fromType and toVert
222
222
neighborsToRemove := []* namedVertex {}
223
- neighborsToRecompute := []* namedVertex {}
223
+ edgesToRemove := []graph. Edge {}
224
224
g .graph .VisitTo (toVert , func (from graph.Node ) bool {
225
225
fromVert := from .(* namedVertex )
226
226
if fromVert .vertexType != fromType {
227
227
return true
228
228
}
229
- // remove the edge
230
- g .graph .RemoveEdge (simple.Edge {F : fromVert , T : toVert })
231
- // track vertexes that changed edges
232
- if g .graph .Degree (fromVert ) == 0 {
229
+ // this neighbor has only one edge (which must be to us), so remove them as well
230
+ if g .graph .Degree (fromVert ) == 1 {
233
231
neighborsToRemove = append (neighborsToRemove , fromVert )
234
232
} else {
235
- neighborsToRecompute = append (neighborsToRecompute , fromVert )
233
+ edgesToRemove = append (edgesToRemove , g . graph . EdgeBetween ( from , toVert ) )
236
234
}
237
235
return true
238
236
})
@@ -242,9 +240,30 @@ func (g *Graph) deleteEdges_locked(fromType, toType vertexType, toNamespace, toN
242
240
g .removeVertex_locked (v )
243
241
}
244
242
245
- // recompute destination indexes for neighbors that dropped outbound edges
246
- for _ , v := range neighborsToRecompute {
247
- g .recomputeDestinationIndex_locked (v )
243
+ // remove edges and decrement destination indexes for neighbors that dropped outbound edges
244
+ for _ , edge := range edgesToRemove {
245
+ g .graph .RemoveEdge (edge )
246
+ g .removeEdgeFromDestinationIndex_locked (edge )
247
+ }
248
+ }
249
+
250
+ // A fastpath for recomputeDestinationIndex_locked for "removing edge" case.
251
+ func (g * Graph ) removeEdgeFromDestinationIndex_locked (e graph.Edge ) {
252
+ n := e .From ()
253
+ // don't maintain indices for nodes with few edges
254
+ edgeCount := g .graph .Degree (n )
255
+ if edgeCount < g .destinationEdgeThreshold {
256
+ delete (g .destinationEdgeIndex , n .ID ())
257
+ return
258
+ }
259
+
260
+ // decrement the nodeID->destinationID refcount in the index, if the index exists
261
+ index := g .destinationEdgeIndex [n .ID ()]
262
+ if index == nil {
263
+ return
264
+ }
265
+ if destinationEdge , ok := e .(* destinationEdge ); ok {
266
+ index .decrement (destinationEdge .DestinationID ())
248
267
}
249
268
}
250
269
@@ -300,12 +319,7 @@ func (g *Graph) recomputeDestinationIndex_locked(n graph.Node) {
300
319
}
301
320
return true
302
321
})
303
-
304
- if len (index .members ) < g .destinationEdgeThreshold {
305
- delete (g .destinationEdgeIndex , n .ID ())
306
- } else {
307
- g .destinationEdgeIndex [n .ID ()] = index
308
- }
322
+ g .destinationEdgeIndex [n .ID ()] = index
309
323
}
310
324
311
325
// AddPod should only be called once spec.NodeName is populated.
0 commit comments