Skip to content
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

Optimize readers searching for matching filenames #1178

Merged
merged 6 commits into from May 7, 2020

Conversation

djhoese
Copy link
Member

@djhoese djhoese commented May 4, 2020

This addresses some of the performance issues mentioned in #1172. Thanks to @gerritholl's investigating, it was discovered that the base reader's functions for searching for file was taking a long time. We've tracked it down to a few key parts, the main one being that globify was called thousands of times for only hundreds of files. The changes in this PR seem to make a big difference.

Here is a PyCharm profiling graph showing the most called or longest running functions in the call graph of my test script:

globify_orig

With a total run time of ~16.5s. Here's what it looks like after this PR (globify is not even listed):

globify_2

With a total run time of ~4.7s.

@djhoese djhoese added enhancement code enhancements, features, improvements component:readers optimization labels May 4, 2020
@djhoese djhoese self-assigned this May 4, 2020
@djhoese
Copy link
Member Author

djhoese commented May 4, 2020

I think I'd like to look at caching these globified patterns so in MultiScene cases they are only globified once. That's my next step although I don't expect it to make a big difference with my current test case.

@mraspaud
Copy link
Member

mraspaud commented May 4, 2020

If globify isn't listed anymore, then maybe the optimization should happen somewhere else now ?

@djhoese djhoese added this to To do in PCW Spring 2020 via automation May 4, 2020
@coveralls
Copy link

Coverage Status

Coverage increased (+0.004%) to 89.612% when pulling 0cbea18 on djhoese:optimize-reader-globify into a82e4a6 on pytroll:master.

@coveralls
Copy link

coveralls commented May 4, 2020

Coverage Status

Coverage increased (+0.01%) to 89.62% when pulling 11e3b4c on djhoese:optimize-reader-globify into a82e4a6 on pytroll:master.

@codecov
Copy link

codecov bot commented May 4, 2020

Codecov Report

Merging #1178 into master will increase coverage by 0.00%.
The diff coverage is 97.36%.

Impacted file tree graph

@@           Coverage Diff           @@
##           master    #1178   +/-   ##
=======================================
  Coverage   89.61%   89.61%           
=======================================
  Files         200      200           
  Lines       29504    29537   +33     
=======================================
+ Hits        26439    26471   +32     
- Misses       3065     3066    +1     
Impacted Files Coverage Δ
satpy/readers/yaml_reader.py 95.30% <96.15%> (-0.13%) ⬇️
satpy/readers/__init__.py 95.10% <100.00%> (+0.01%) ⬆️
satpy/tests/test_readers.py 98.98% <100.00%> (+0.02%) ⬆️
satpy/tests/test_yaml_reader.py 99.78% <100.00%> (ø)
satpy/tests/reader_tests/test_fci_l1c_fdhsi.py 100.00% <0.00%> (ø)
satpy/readers/fci_l1c_fdhsi.py 96.37% <0.00%> (+0.16%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update a82e4a6...11e3b4c. Read the comment docs.

@djhoese
Copy link
Member Author

djhoese commented May 4, 2020

Did a quick MultiScene test trying to create 60 Scenes using MultiScene.from_files with the current changes from this PR:

satpy_multiscene_2

Takes 37 seconds to create 60 Scenes. Not sure that is good or bad.

@djhoese
Copy link
Member Author

djhoese commented May 4, 2020

We could think about using asv to perform some benchmark tests: https://tomaugspurger.github.io/maintaing-performance.html

If we wanted this semi-automated we could add it to the integration tests on Jenkins (running on the SSEC's bumi server).

@djhoese
Copy link
Member Author

djhoese commented May 4, 2020

Ok, after answering messages and taking a break for a bit, I started playing around with lru_cache (from functools in the standard library) and added it to some key points where patterns were being used. It cut the timing down to 2.8s total.

globify_3

On slack @mraspaud had brought up making parser faster, but I wasn't sure that was possible since it is a lower-level function. This caching shows it is possible. We just have to control it well so we don't fill up people's disk or hold on to too much (the default is 128 items I think).

I'd still like to restructure some of the stuff in Satpy as it is needlessly calling some of these functions. I'll see what I can do.

@djhoese
Copy link
Member Author

djhoese commented May 4, 2020

Ok I think I'm done with all of the satpy-specific optimizations, but I have a related refactor I want to do. @mraspaud what are your thoughts on renaming some of the internal functions so they have _ at the front? @gerritholl has asked if some functions are considered public interfaces. Some of them are, sure, but others shouldn't be. I'd like to do prefix some of these with _ so I can more easily justify require a set object as input rather than converting to a set first everywhere.

Edit: I still need to make a trollsift PR. I'm not sure any of the changes here need tests since they are all refactors.

@djhoese
Copy link
Member Author

djhoese commented May 4, 2020

See pytroll/trollsift#25 for trollsift optimization.

@djhoese
Copy link
Member Author

djhoese commented May 4, 2020

Here is the pycharm profiling graph after both these sets of changes (total run time ~2.3s):

globify_4

@djhoese djhoese moved this from To do to In progress in PCW Spring 2020 May 4, 2020
PCW Spring 2020 automation moved this from In progress to Ready to merge May 5, 2020
Copy link
Member

@mraspaud mraspaud left a comment

Choose a reason for hiding this comment

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

LGTM. We might want to plan for using asv in the future...

@gerritholl
Copy link
Collaborator

I tried this with the latest trollsift master and also #1169 merged. With the same test script as before. New times are:

  • 125 fake files: 40 calls to globify, 0.14 seconds for find_files_and_readers (previously 5.12 seconds).
  • 1000 fake files: 40 calls to globify, 0.28 seconds for find_files_and_readers.
  • 60000 fake files: 40 calls to globify, 12.4 seconds for find_files_and_readers.

satpy/readers/yaml_reader.py Outdated Show resolved Hide resolved
satpy/readers/yaml_reader.py Outdated Show resolved Hide resolved
@djhoese
Copy link
Member Author

djhoese commented May 5, 2020

I think I've addressed everything @gerritholl mentioned and I'm ready for a re-review and merge assuming the tests pass.

@gerritholl
Copy link
Collaborator

Excellent work, thanks. All good as far as I can tell :)

Copy link
Member

@mraspaud mraspaud left a comment

Choose a reason for hiding this comment

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

LGTM

@mraspaud mraspaud merged commit 5343a83 into pytroll:master May 7, 2020
PCW Spring 2020 automation moved this from Ready to merge to Done May 7, 2020
@djhoese djhoese deleted the optimize-reader-globify branch May 7, 2020 12:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component:readers enhancement code enhancements, features, improvements optimization
Projects
Development

Successfully merging this pull request may close these issues.

find_files_and_readers is slow
4 participants