Skip to content

concretizer: add mode to reuse dependencies only#30990

Merged
alalazo merged 1 commit intospack:developfrom
michaelkuhn:concretizer-reuse-deps
Mar 14, 2023
Merged

concretizer: add mode to reuse dependencies only#30990
alalazo merged 1 commit intospack:developfrom
michaelkuhn:concretizer-reuse-deps

Conversation

@michaelkuhn
Copy link
Copy Markdown
Member

@michaelkuhn michaelkuhn commented Jun 4, 2022

This adds a new mode for concretizer:reuse called dependencies, which only reuses dependencies. Currently, spack install foo will reuse older versions of foo, which might be surprising to users.

I'm not entirely happy with the argument name (--reuse-deps) yet and would argue for making this the default reuse mode.

@spackbot-app spackbot-app bot added defaults tests General test capability(ies) labels Jun 4, 2022
@michaelkuhn michaelkuhn force-pushed the concretizer-reuse-deps branch 2 times, most recently from a0b9ec1 to cb033f8 Compare June 4, 2022 11:36
@alalazo alalazo self-requested a review June 4, 2022 12:19
@alalazo alalazo self-assigned this Jun 4, 2022
@michaelkuhn michaelkuhn force-pushed the concretizer-reuse-deps branch from cb033f8 to a514b38 Compare October 16, 2022 19:29
@spackbot-app spackbot-app bot added the core PR affects Spack core functionality label Oct 16, 2022
@michaelkuhn michaelkuhn force-pushed the concretizer-reuse-deps branch from a514b38 to 559e141 Compare October 16, 2022 19:33
@michaelkuhn
Copy link
Copy Markdown
Member Author

@alalazo I have fixed the conflicts and rebased to current develop. Any comments about this change?

@michaelkuhn michaelkuhn force-pushed the concretizer-reuse-deps branch from 559e141 to e9dbee9 Compare October 21, 2022 05:42
@haampie
Copy link
Copy Markdown
Member

haampie commented Oct 21, 2022

@becker33 can you coordinate your "reuse from local installs/upstreams" vs "reuse from binary cache" with this PR? Just to avoid that we're ending up with --reuse="locally installed but not the root spec please"

@tgamblin tgamblin added this to the v0.20.0 milestone Nov 7, 2022
@adamjstewart
Copy link
Copy Markdown
Member

@becker33 you mentioned that this PR would need some work to update for changes in develop since it was created. What changes are required? Would love to get this in soon, as I think this is the most logical default concretization strategy.

@michaelkuhn michaelkuhn force-pushed the concretizer-reuse-deps branch from e9dbee9 to 5aa6767 Compare November 17, 2022 07:56
@michaelkuhn
Copy link
Copy Markdown
Member Author

I rebased this to current develop to fix some conflicts. I also did some tests and it still seems to work.

adamjstewart
adamjstewart previously approved these changes Nov 18, 2022
Copy link
Copy Markdown
Member

@adamjstewart adamjstewart left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested this with a few individual packages and a massive environment and it works perfectly, exactly the behavior I would find most intuitive. Great job on this!

@tgamblin tgamblin self-requested a review December 2, 2022 23:09
@michaelkuhn
Copy link
Copy Markdown
Member Author

@tgamblin @becker33 ping?

Comment on lines +2409 to +2525
# If we only want to reuse dependencies, remove the root specs
if self.reuse == "dependencies":
reusable_specs = [
spec for spec in reusable_specs if not any(spec.satisfies(root) for root in specs)
]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is redundant, since it includes specs that have a root as a dependency. The solve will rule that out, but potentially we have more hashes than we want as facts. Did you try:

Suggested change
# If we only want to reuse dependencies, remove the root specs
if self.reuse == "dependencies":
reusable_specs = [
spec for spec in reusable_specs if not any(spec.satisfies(root) for root in specs)
]
# If we only want to reuse dependencies, remove the root specs
if self.reuse == "dependencies":
reusable_specs = [
spec for spec in reusable_specs if not any(root in spec for root in specs)
]

?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might be reading the code wrong but aren't we hitting the anonymous case in __contains__ anyway, which simply calls satisfies: https://github.com/spack/spack/blob/develop/lib/spack/spack/spec.py#L4001-L4002
I would therefore assume that this behaves identically. I also did some tests and couldn't provoke any differences.

Copy link
Copy Markdown
Member

@alalazo alalazo Dec 12, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reusable specs are all concrete specs collected either from the DB or from buildcaches, root specs can't be anonymous. I checked the ASP before posting. Result is the same, we just have a lot of input in the ASP which is useless.

Try for instance:

  1. Install hdf5+mpi (fake installs are good for this test)
  2. Create an environment with hdf5+mpi and zlib as root specs + reuse:dependencies
  3. spack solve --show=asp for the environment

I think you'll see all the specs in there, but hdf5 and zlib There are specs though that reference the non-existing zlib and thus will never be selected.

I think there might be other potential pitfalls we might need to check, e.g. if I can reuse the same package as the root but with different variant in an environment. Going back to the example above do we want to reuse hdf5~mpi if it is installed, since the the root says hdf5+mpi? That matters if we have a root spec that depend on hdf5. I didn't test-drive that case yet.

Copy link
Copy Markdown
Member Author

@michaelkuhn michaelkuhn Dec 12, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I got what you meant now, thanks! I confused myself with the "root specs" in the snippet above and actually tested it outside of an environment (which hits the anonymous spec path).

I now did some tests inside an environment and could reproduce your results. I guess the interaction can be a bit surprising if a common dependency is a root spec: I added a new cmake version but since zlib is a root spec and thus filtered out, cmake gets rebuilt even though it could theoretically be reused. I guess there is no way around that, though.

If I add enzo (which requires hdf5~mpi) in your example above, everything seems to continue working as expected:

==> Error: 'hdf5' required multiple values for single-valued variant 'mpi'
    Requested '~mpi' and '+mpi'

I also made the change you suggested and pushed a new version.

@michaelkuhn michaelkuhn force-pushed the concretizer-reuse-deps branch 3 times, most recently from 130768b to 02e7a56 Compare December 13, 2022 08:07
@adamjstewart
Copy link
Copy Markdown
Member

Any updates on this? I find myself needing this behavior again today. My new use case:

I often fix bugs in packages and want to build them to make sure the fix works. I'm faced with two options:

  1. spack install foo: the package is already installed
  2. spack install --fresh foo: rebuild the entire world

I would love the feature added in this PR (even more so if it becomes the default):

  1. spack install --reuse-deps foo: only build foo

@michaelkuhn
Copy link
Copy Markdown
Member Author

Any updates on this? I find myself needing this behavior again today. My new use case:

I incorporated @alalazo's feedback a while ago, so it should now work better in environments. From my side, this is good to go.

@michaelkuhn
Copy link
Copy Markdown
Member Author

I still run into this every time I update a package:

$ spack install foo
# already installed
$ spack install foo@x.y.z

@alalazo ping 🙂

@alalazo
Copy link
Copy Markdown
Member

alalazo commented Mar 1, 2023

I'll try to review this one by the end of the week.

alalazo
alalazo previously approved these changes Mar 6, 2023
Copy link
Copy Markdown
Member

@alalazo alalazo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. I left a few minor comments. Let's wait a bit to check if people have opinion on the cli flag, otherwise this is ready to be merged.

pass

# If we only want to reuse dependencies, remove the root specs
if self.reuse == "dependencies":
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Comment, not request): If we add more reuse modes, it is worth turning these literal strings into enums.

Comment on lines +424 to +525
subgroup.add_argument(
"--reuse-deps",
action=ConfigSetAction,
dest="concretizer:reuse",
const="dependencies",
default=None,
help="reuse installed dependencies only",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(nitpick) Not sure this is the best way to deal with the command line, but I think this should not be a feature blocker. What I wonder is if:

--reuse=<argument>

is better and more scalable in general, and if we can deprecate the current --fresh argument. @tgamblin @becker33 @haampie Any opinion on this?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not to say I told you so, but... #28468 (comment)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't touched this one since @adamjstewart mentioned on Slack that supporting both --reuse and --reuse=foo doesn't seem to be possible.

This adds a new mode for `concretizer:reuse` called `dependencies`,
which only reuses dependencies. Currently, `spack install foo` will
reuse older versions of `foo`, which might be surprising to users.
@michaelkuhn michaelkuhn force-pushed the concretizer-reuse-deps branch from c077f63 to ac633d3 Compare March 8, 2023 20:47
@adamjstewart
Copy link
Copy Markdown
Member

Is there any special handling (in this PR or already in Spack) for handling deprecated versions? Like if one of my packages becomes deprecated, I might not want it to be reused even if it's already installed.

@alecbcs
Copy link
Copy Markdown
Member

alecbcs commented Mar 13, 2023

I don't know of any existing deprecated logic but I too would love this!

@adamjstewart
Copy link
Copy Markdown
Member

Either way, it shouldn't hold up this PR since we already reuse everything by default. If there isn't logic to avoid deprecated versions yet, we can add it in a follow-up PR.

@alecbcs
Copy link
Copy Markdown
Member

alecbcs commented Mar 13, 2023

At the moment are there any blockers for this PR? It looks like perhaps we're waiting on final say about --fresh vs --reuse= options? Or is that just a conversation starter for a follow up?

@alalazo
Copy link
Copy Markdown
Member

alalazo commented Mar 14, 2023

At the moment are there any blockers for this PR? It looks like perhaps we're waiting on final say about --fresh vs --reuse= options? Or is that just a conversation starter for a follow up?

I was waiting for that, but since I got no objections to the current state of the PR nor other comments I'll merge this. If objections come up later we can take care of them in a following PR.

@alalazo alalazo merged commit 5bae742 into spack:develop Mar 14, 2023
cnegre pushed a commit to cnegre/spack that referenced this pull request Mar 20, 2023
This adds a new mode for `concretizer:reuse` called `dependencies`,
which only reuses dependencies. Currently, `spack install foo` will
reuse older versions of `foo`, which might be surprising to users.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

concretization core PR affects Spack core functionality defaults tests General test capability(ies)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants