-
Notifications
You must be signed in to change notification settings - Fork 214
Avoid using a priority in prepend_module_path (Lmod) to avoid costly module calls #3636
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
Avoid using a priority in prepend_module_path (Lmod) to avoid costly module calls #3636
Conversation
49093a6 to
9f82a1b
Compare
|
@Flamefire Let's close #3634 and continue the discussion here. When this PR (#3636) gets merged, #3634 will also be merged automatically (since the commits included in here are also included in there), but context w.r.t. the discussion will be missing... |
easybuild/tools/modules.py
Outdated
| priority = self.HIGH_PRIORITY | ||
| self.use(path, priority=priority) | ||
| modulepath = curr_module_paths(clean=False) | ||
| path_idx = modulepath.index(path) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could trigger a ValueError if (somehow...) path is not in $MODULEPATH, so maybe wrap this in a try/except to avoid a nasty traceback?
It would be really weird to not have path at all in modulepath though, I must admit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be virtually impossible for this to happen as it should be either caught already by our tests or is an actual (and serious) bug in Lmod. So I'd say the "nasty traceback" is fine in this rare case so we don't need to litter our code :)
easybuild/tools/modules.py
Outdated
|
|
||
|
|
||
| def curr_module_paths(): | ||
| def curr_module_paths(clean=True): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wouldn't make cleaning optional at all, I think weird things may happen when empty values are included in $MODULEPATH and EasyBuild starts using those. There's a reason we're filtering those here...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is required to match Lmod behavior: Lmod uses any path as specified, so non-existing, empty or "unusual" ones are just used.
So the "fast" module use/unuse must use the non-cleaned path or behavior will differ
There's a reason we're filtering those here...
Remember which? Also the default is still to clean, so all of EB except for the new functions is unaffected
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From Slack:
we do need a
clean_existing_pathsforcurr_module_paths, but it should still filter out empty paths
Why? I don't even think we should clean out non-existing paths by default and filtering out empty paths would be different from what Lmod does, although I'm not sure about the semantic of that. And if we do filter those, then the fast and regular module.use would be different.
easybuild/tools/modules.py
Outdated
|
|
||
| def unuse(self, path): | ||
| """Remove a module path""" | ||
| # We can simply remove the path from MODULEPATH to avoid the costly module call |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
costly "module unuse" call
Maybe also clarify that modifying $MODULEPATH directly implies that Lmod won't reconsider loaded modules, but in the context of an EasyBuild session that should be OK...
Maybe we should also add an option to force running the actual module unuse command (same above for use), in case people are using the EasyBuild interface to the modules tool in Python scripts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done with default set to False to provide the fast implementation by default
easybuild/tools/modules.py
Outdated
| self.use(path, priority=priority) | ||
| modulepath = curr_module_paths(clean=False) | ||
| path_idx = modulepath.index(path) | ||
| if path_idx != 0: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we notice the path isn't first, can't we try again with self.use(path, priority=priority, force_module_command=True)?
The warning should suffice to make it clear something fishy is going on, but we can still try to do the correct thing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This wouldn't change anything: If priority is None, then the path will be at the front already due to the fast path, if priority is not None or any priorities are in use then the module command will be used already.
|
@Flamefire Conflict resolution needed |
1d62274 to
59af049
Compare
|
Rebased and conflicts resolved. That was quite a lot... Please double-check the changes |
59af049 to
2f85eaa
Compare
|
This now looks good to me, but since it's large i'll wait for @boegel to review before merging. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
926efa6 to
735c24c
Compare
| os.environ['MODULEPATH'] = old_module_path # Restore | ||
|
|
||
| # Forcing to use the module command reloads modules (Only Lmod does this) | ||
| old_module_path = os.environ['MODULEPATH'] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line is superfluous, old_module_path is already == os.environ['MODULEPATH']
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually the "os.environ... Restore" line above is also useless since you're setting it again below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right, but those are more or less different (sub-)testcases. I wanted to make them self-contained, so it would still work if we remove one of those. Maybe best done via a fixture or context-manager but yeah...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW: #5015 introduces a context manager that can be used here
Lmod ignores if a path exists so we should be able to do the same
Introduce _set_module_path which correctly handles empty paths and empty lists with proper logging
670ea75 to
a503b87
Compare
|
There is one failing test where we should consider what we want: If the caller of This currently happens in a test: |
If a path was added with priority, that was likely done with good reason, so we should respect that... This recently popped up actually, see c8e723a (which is part of #4991) |
|
This could be easily done by removing: I can do that. |
$MODULEPATH to avoid costly module calls
$MODULEPATH to avoid costly module calls|
This is no longer useful as priorities need to be used when specified and so we might end up with I kept the relevant changes from this PR and opened a new one: #5030 @boegel This includes 2 important bugfixes I discovered with the added tests |
This PR avoids using a priority in
prepend_module_path(Lmod) which means that $MODULEPATH can be directly modified by this and all subsequent calls to eitherprepend_module_pathorusewhich is a lot faster than calling Lmod.The test has been changed so it now expects that
prepend_module_pathactually does prepend even when no priority is passed and another priority is in effect.For compatibility I kept the constant
10000asHIGH_PRIORITYso user sites that really want other module paths to take preference can use any higher priority.As discussed in Slack this change is unlikely to effectively change any behavior and will very likely continue to work, see TACC/Lmod#509 (comment)
Fixes #3631