Skip to content

feat: deduplicate shared URL downloads across test suites#338

Open
dabrain34 wants to merge 1 commit into
fluendo:masterfrom
dabrain34:dab_duplication_download
Open

feat: deduplicate shared URL downloads across test suites#338
dabrain34 wants to merge 1 commit into
fluendo:masterfrom
dabrain34:dab_duplication_download

Conversation

@dabrain34

@dabrain34 dabrain34 commented Feb 26, 2026

Copy link
Copy Markdown
Contributor

Introduce a centralized DownloadManager that ensures each URL is downloaded at most once, eliminating duplicate downloads both across test suites and within a single test suite.

  • Add DownloadManager class in utils.py with download-once caching and centralized archive cleanup
  • Refactor TestSuite.download() to use pre-downloaded archives from the manager across all three download paths
  • Use a thread pool to download concurrently and make DownloadManager thread-safe so duplicate URLs are still fetched only once.

This feature allows to fast up considerably the download of AV1-ARGON* which was downloading each time the 6GB archive for every test vector.

Fix #309

@dabrain34

Copy link
Copy Markdown
Contributor Author

@ylatuya ping

@dabrain34

dabrain34 commented Apr 21, 2026

Copy link
Copy Markdown
Contributor Author

@rsanchez87 can you have a look to this PR as well? The idea would be to fast up the build of docker images containing all the test suites

Comment thread fluster/test_suite.py Outdated
Comment thread fluster/test_suite.py Outdated
Comment thread fluster/test_suite.py Outdated
Comment thread fluster/test_suite.py Outdated
Comment thread fluster/test_suite.py Outdated
return (url, local_path)

max_workers = max(1, min(jobs, len(unique_source_list)))
with ThreadPoolExecutor(max_workers=max_workers) as dl_pool:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We use Pool from multiprocessing

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The idea is to move all the logic for download pool inside the download manager which handled the dedup, the thread lock, the extraction and everything to download through ThreadPoolExecutor.

Do you have a preference for multiprocessing for a reason ?

Comment thread fluster/test_suite.py Outdated
@rsanchez87

Copy link
Copy Markdown
Contributor

@rsanchez87 can you have a look to this PR as well? The idea would be to fast up the build of docker images containing all the test suites

@dabrain34, tested with python3 fluster.py download AV1-ARGON-PROFILE0-CORE-ANNEX-B AV1-ARGON-PROFILE1-CORE-ANNEX-B AV1-ARGON-PROFILE2-CORE-ANNEX-B
master: 49m 40s
PR: 16m 2s (~3x faster, ZIP downloaded once instead of 3 times) ✅

Also regression tests ✔️

I’ll test again once the requested changes by @ylatuya are implemented. Thanks!

@dabrain34

Copy link
Copy Markdown
Contributor Author

thanks for the test, indeed this is even better on low speed lines as we dont redownload all the time the AV1 zip file.

I'm currently addressing comments from ylatuya. When this is ready I will come back to you

@dabrain34
dabrain34 force-pushed the dab_duplication_download branch from dc31a68 to a3b3d5f Compare May 22, 2026 13:27
@dabrain34
dabrain34 marked this pull request as draft May 22, 2026 13:46
@dabrain34
dabrain34 force-pushed the dab_duplication_download branch from a3b3d5f to 2bfdac4 Compare May 25, 2026 11:58
@dabrain34
dabrain34 marked this pull request as ready for review May 27, 2026 04:17
@1ace

1ace commented Jul 1, 2026

Copy link
Copy Markdown

@dabrain34 @ylatuya was the question of using threads vs processes resolved in another channel perhaps?

Is there anything else blocking this from being merged?

@ylatuya

ylatuya commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

@dabrain34 I think the current implementation is overly complicated for what it's trying to achieve, the download logic is now spread in the DownloadManager and the TestSuite itself.

My proposal in the previous review may not have been expressed clearly, but what I was proposing is to move all the existing download logic from TestSuite, which already supports parallel downloads and deduplication, into a new DownloadManager. The new DownloadManager.download should now accept a list of test suites to support deduplication and parallel downloads over multiple test suites. The DownloadManager should also manage a shared cache for downloaded sources.

Fluster.download_test_suites uses the DownloadManager directly, from this:

     for test_suite in download_test_suites:
            test_suite.download(
                jobs,
                self.resources_dir,
                verify=True,
                keep_file=keep_file,
                retries=retries,
            )

To this:

    download_manager = DownloadManager(jobs, self.resources_dir, verify=True, keep_file=keep_file, retries=retries)
    dowload_manager.download(download_test_suites)

TestSuite.download uses the manager as well (I think we can even remove this method from TestSuite, it shouldn't be needed)

    def download(
        self,
        jobs: int,
        out_dir: str,
        verify: bool,
        extract_all: bool = False,
        keep_file: bool = False,
        retries: int = 2,
    ) -> None:
        """
             Download the test suite resources.
        """
        manager = DownloadManager(out_dir, verify, extract_all, keep_file, retries)
        manager.download([self], jobs)

This approach simplifies things since all the download logic is kept in a single place, the DonwloadManager, and than Fluster uses that to download test suites.

@ylatuya

ylatuya commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

@dabrain34, this is an example of how I would like the implementation to look like ylatuya@4bfa256. (There seems to be a bug in Github that does not include the changes in utils.py in the diff)

That way, we keep all the download logic in a single place, the DownloadManager, so that new features like #362 can be implemented in a single place.

@dabrain34

Copy link
Copy Markdown
Contributor Author

I'm about to push something where utils.py has been replaced by download_manager.py

@dabrain34
dabrain34 force-pushed the dab_duplication_download branch from 2bfdac4 to e71aa18 Compare July 10, 2026 15:29
@dabrain34

Copy link
Copy Markdown
Contributor Author

I think I addressed your request by moving all the downloadmager code to a specific file and move the test suite download to this module as well. Please give it a try and let me know.

@dabrain34
dabrain34 force-pushed the dab_duplication_download branch from e71aa18 to 6321d15 Compare July 10, 2026 15:38
Introduce a centralized DownloadManager so each URL is downloaded at
most once, both within and across selected suites. Saves re-fetching
multi-GB archives like AV1-ARGON shared by 12 suites.

DownloadManager (fluster/download_manager.py):
- Thread-safe per-URL caching at resources/.cache/; concurrent get()
  calls on the same URL block on the in-flight download.
- BoundedSemaphore caps HTTP concurrency at 8.
- Per-URL retry budget; ChecksumMismatchError poisons immediately.
- invalidate(url) lets consumers drop a corrupt cached archive.
- Context manager: cleanup() runs via __exit__, honoring keep_file.
- filename_from_url() strips query strings for safe on-disk names.

DownloadManager.download_test_suite() (fluster/download_manager.py):
- Owns all three download paths (single archive, single file, multi-TV).
- Multi-TV branch pre-downloads unique URLs in parallel before the
  multiprocessing extraction pool.
- Raw source files are moved out of the cache (no double storage).
- Moved out of TestSuite, which is now a pure data/test domain object.

CLI (fluster/fluster.py):
- Three-phase: collect URLs across selected suites, parallel
  pre-download, per-suite extraction. Cross-suite parallelism is the
  main user-visible win.
- All callers (CLI + 7 scripts/gen_*.py) use the with-statement form.
@dabrain34
dabrain34 force-pushed the dab_duplication_download branch from 6321d15 to 388a4b4 Compare July 10, 2026 16:13
@dabrain34

dabrain34 commented Jul 18, 2026

Copy link
Copy Markdown
Contributor Author

so you merged #362 first which leads this PR to conflicts (again).

I think it would have been better to review and merge this first as it was modifying the download mechanism for real performance improvement in comparison to mirror.

The AV1 test suite download repeats the 6.5GB DL on every test vector, it has to be improved for CI purpose, see Mesa CI.

@dabrain34

Copy link
Copy Markdown
Contributor Author

Please let me know if I should invest more time on rebasing and resolving conflicts as it might enter your roadmap.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Downloading the AV1 test suites results in downloading multiple times a 6GB archive

4 participants