Remove m*n locking from resource evaluation and O(m * n * (m+n)) iteration (#2835)

Signed-off-by: Christian Mesh <christianmesh1@gmail.com>
Co-authored-by: Andrei Ciobanu <andrei.ciobanu@opentofu.org>
This commit is contained in:
Christian Mesh
2025-05-23 09:47:29 -04:00
committed by GitHub
parent 07b8a3f0cb
commit edfc680d94

View File

@@ -747,6 +747,17 @@ func (d *evaluationStateData) GetResource(addr addrs.Resource, rng tfdiags.Sourc
}
}
// Fetch all instance data in a single call. We previously used GetResourceInstanceChange in
// each loop iteration which caused n^2 locking contention. This is especially problematic for
// resources with large count/for_each.
instChanges := d.Evaluator.Changes.GetChangesForConfigResource(addr.InModule(moduleConfig.Path))
instMap := map[string]*plans.ResourceInstanceChangeSrc{}
for _, rc := range instChanges {
if rc.DeposedKey == states.NotDeposed {
instMap[rc.Addr.String()] = rc
}
}
// Decode all instances in the current state
instances := map[addrs.InstanceKey]cty.Value{}
pendingDestroy := d.Operation == walkDestroy
@@ -759,7 +770,7 @@ func (d *evaluationStateData) GetResource(addr addrs.Resource, rng tfdiags.Sourc
instAddr := addr.Instance(key).Absolute(d.ModulePath)
change := d.Evaluator.Changes.GetResourceInstanceChange(instAddr, states.CurrentGen)
change := instMap[instAddr.String()]
if change != nil {
// Don't take any resources that are yet to be deleted into account.
// If the referenced resource is CreateBeforeDestroy, then orphaned