Skip to content

Solver: Deduplicate LinkGroup's potential conflict set #3267

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from

Conversation

grayjay
Copy link
Collaborator

@grayjay grayjay commented Apr 1, 2016

This commit stores the potential conflict set in a set instead of a list. The deduplication prevents a LinkGroup from growing exponentially when it is merged with itself multiple times.

This is one reason that the solver quickcheck test (#3245) ran out of memory, though the problem doesn't seem likely to occur with real packages. Here is a simplified version of the test case: grayjay@5297f3a. I didn't include it in the PR because it only fails when the solver handles goals in a specific order, and that order seems to depend on a bug.
EDIT: The bug is #3268.

After the solver links 2.C to 0.C-1.0.0 and chooses +flagA for 2.C-1.0.0, it needs to merge the LinkGroups of the dependencies introduced by flagA with the LinkGroups of the corresponding packages that are qualified with 0. flagA introduces a dependency on D-3 multiple times. For the first dependency, the solver merges 0.D and 2.D's LinkGroups. For each of the remaining dependencies on D-3, the solver merges the new link group with itself. The field lgBlame :: [Var QPN] doubles in length each time.

[...]
          runTest $ indep $ mkTest dbRepeatedConstraints "repeated constraints" ["A", "B", "C"] $
              Just [("A", 1), ("B", 1), ("C", 1), ("D", 2)]
[...]

dbRepeatedConstraints :: ExampleDb
dbRepeatedConstraints = [
    Right $ exAv "A" 1 [ExAny "B", ExAny "C", ExAny "D"]
  , Right $ exAv "B" 1 [] `withSetupDeps` [ExAny "C", ExAny "D"]
  , Right $ exAv "C" 1 $ replicate 15 $
        exFlag "flagA" [ExFix "D" 3] []
  , Right $ exAv "D" 1 []
  , Right $ exAv "D" 2 []
  ]

Complete log from a run that included this PR:

      repeated constraints:                             targets: A, B, C
constraints:
  stanzas A test (unknown source)
  stanzas B test (unknown source)
  stanzas C test (unknown source)
  stanzas D test (unknown source)
  stanzas D test (unknown source)
preferences:
strategy: PreferLatestForSelected
reorder goals: False
independent goals: True
avoid reinstalls: False
shadow packages: False
strong flags: False
max backjumps: infinite
[__0] trying: 0.A-1.0.0 (user goal)
[__1] trying: 0.D-2.0.0 (dependency of 0.A-1.0.0)
[__2] trying: 0.C-1.0.0 (dependency of 0.A-1.0.0)
[__3] trying: 0.B-1.0.0 (dependency of 0.A-1.0.0)
[__4] trying: 1.B~>0.B-1.0.0 (user goal)
[__5] trying: 2.C~>0.C-1.0.0 (user goal)
[__6] trying: 2.C-1.0.0:+flagA
[__7] next goal: 2.D (dependency of 2.C-1.0.0:+flagA)
[__7] rejecting: 2.D~>0.D-2.0.0 (conflict: 2.C-1.0.0:flagA => 2.D==3.0.0)
[__7] rejecting: 2.D-2.0.0 (multiple instances)
[__7] rejecting: 2.D-1.0.0 (dependencies not linked: cannot make 2.D canonical member of {*0.D-2.0.0,2.D-2.0.0,B-setup.1.D-2.0.0}; conflict set: 1.B, 2.C, 2.D, 2.C-1.0.0:flagA)
[__7] fail (backjumping, conflict set: 0.D, 1.B, 2.C, 2.D, 2.C-1.0.0:flag, 2.C-1.0.0:flagA)
[__6] trying: 2.C-1.0.0:-flagA
[__7] rejecting: 0.C-1.0.0:+flagA (dependencies not linked: flag FlagName "flagA" incompatible; conflict set: 0.C, 1.B, 2.C, B-setup.1.C, 0.C-1.0.0:flagA, 2.C-1.0.0:flagA, B-setup.1.C-1.0.0:flagA)
[__6] fail (backjumping, conflict set: 0.C, 1.B, 2.C, B-setup.1.C, 0.C-1.0.0:flagA, 2.C-1.0.0:flagA, B-setup.1.C-1.0.0:flagA)
[__5] rejecting: 2.C-1.0.0 (multiple instances)
[__5] fail (backjumping, conflict set: 0.C, 1.B, 2.C, B-setup.1.C, 0.C-1.0.0:flagA, 2.C-1.0.0:flagA, B-setup.1.C-1.0.0:flagA)
[__4] rejecting: 1.B-1.0.0 (multiple instances)
[__0] fail (backjumping, conflict set: 0.B, 0.C, 1.B, 2.C, B-setup.1.C, 0.C-1.0.0:flagA, 2.C-1.0.0:flagA, B-setup.1.C-1.0.0:flagA)
FAIL (0.01s)

This commit stores the potential conflict set in a set instead of a list. The
deduplication prevents a 'LinkGroup' from growing exponentially when it is
merged with itself multiple times.
@ezyang
Copy link
Contributor

ezyang commented Apr 1, 2016

👍 Nice and simple.

@grayjay
Copy link
Collaborator Author

grayjay commented Apr 1, 2016

@ezyang Thanks!

@23Skidoo
Copy link
Member

23Skidoo commented Apr 1, 2016

LGTM as well.

/cc @kosmikus

@ezyang
Copy link
Contributor

ezyang commented Apr 2, 2016

Mysteriously, these changes seem to already be in nix-local-build, they're called ConflictSet. But they don't seem to have been merged into master?!

@grayjay
Copy link
Collaborator Author

grayjay commented Apr 3, 2016

@ezyang What a coincidence! #3234 contains the change that you mentioned, so I'll close this.

@grayjay grayjay closed this Apr 3, 2016
@grayjay grayjay deleted the deduplicate-lgBlame branch April 25, 2016 22:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants