-
Notifications
You must be signed in to change notification settings - Fork 93
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
config parsing optimization #170
Comments
On my desktop box, the suite takes 32s to validate with the current cylc master head. Notably, increasing the number of families has a big impact even though the inheritance graph is just root -> FAM1 -> FAM2 -> FAM3 -> FAM4 -> (all tasks). Here's what I found after some execution profiling with cProfile, and code analysis:
|
With the following changes I can get a full validation of the above suite down to less than 5 seconds, and get-config for a single task to less than 2 seconds:
|
A small step back from the gains reported above, unfortunately - the test battery showed up a problem in my new inheritance implementation. The result now, for the above test suite, is 9s to validate and 5s to get-config a single item from a task, down from 32s (on my desktop box). Still a factor of 3 or more. This may represent the best we can get, pretty much, without more radical changes to the way cylc parses suites to define task proxy classes, etc. |
I've merged this work into master: 6fbbfd3 |
So, the current state of affairs in suite.rc parsing is this: several unnecessary inefficiencies have been removed and inheritance is now done entirely with sparse structures (just what is specified in the suite.rc file), but the full dense structure (including defaults for all possible values) is fleshed out in every dynamically-generated task proxy class definition (one for every task in the graph). Thus we are computing the runtime config data more efficiently but we are still storing a full runtime structure for every task in the suite - which may result in heavy memory requirements for large suites? It might further improve things, at least in terms of memory usage, to not store the final dense runtime structure for every task, but to generate it on the fly every time it is needed (at run time: just before job submission). Then, memory requirement on parsing the suite would be just be the information in the suite.rc file with inheritance expanded out. Validation and get-config would still have to flesh out the defaults for each task, but would not have to hold all tasks in memory at once. We could even go one step further and only do inheritance processing on the fly, just before job submission. Then memory requirement on parsing the suite would just be for exactly what's recorded in the suite.rc file (i.e. common values factored out by inheritance would still be stored just once). However, we might still want "inherit out" higher levels of the hierarchy to avoid much repetition (e.g. in "root -> fam -> (m1, m2, m3)" do we want to re-do "root -> fam" for every member task, or just once? - maybe the repetition doesn't matter if it happens just prior to job submission inside the job submission worker thread. It may even be possible to do absolutely everything on the fly for each task just prior to job submission (or as required for validation and get-config), i.e. parse the suite.rc file anew each time but compute as little as possible, just the data required for the task of interest. This seems a rather extreme solution though! |
Originally, config.py parsed and validated the suite and computed everything required to populate the initial task pool for running the suite. Then get-config came along, to extract individual items from the end result. Now get-config is a bit more efficient in that it tries to only process the particular task targeted by a request, and its ancestors. We can probably make get-config even more efficient by taking only requested [runtime] items of targeted tasks through the inheritance process. And also, by not doing any inheritance or graph parsing at all for get-config of non-[runtime] items. A bit of refactoring of config.py would be nice, to enable this kind of flexibility without loads of if-then constructs embedded in code originally designed to parse the entire suite prior to running it. |
The changes made already have been deemed sufficient for the 5.0 milestone. I'm closing this now, having moved ideas for further improvements to Issue #184. |
As reported by @matthewrmshin: the following 1000-task suite takes > 40 seconds to validate on his desktop, which is a problem for use of "cylc get-config" in an event handler script. Memory usage is also very high during the suite parsing.
The text was updated successfully, but these errors were encountered: