Skip to content

fix: deduplicate shared downloads across test suites - #390

Merged
rsanchez87 merged 6 commits into
fluendo:masterfrom
ylatuya:download-dedup
Sep 29, 2026
Merged

rsanchez87 merged 6 commits into
fluendo:masterfrom
ylatuya:download-dedup

Conversation

@ylatuya

@ylatuya ylatuya commented Sep 21, 2026

Copy link
Copy Markdown
Contributor

Test suites that share a source URL (such as the multi-GB AV1-ARGON archive used by a dozen suites) used to download it once per suite. This introduces a single DownloadManager (fluster/download_manager.py) that fetches each unique source exactly once for the entire selection, then distributes and extracts it wherever needed.

Based on the review of #338.

cc @dabrain34

Comment thread fluster/download_manager.py Outdated
Comment thread fluster/download_manager.py Outdated
Comment thread fluster/download_manager.py Outdated
Comment thread fluster/download_manager.py
@ylatuya
ylatuya force-pushed the download-dedup branch 2 times, most recently from 73eecd5 to 10cffd4 Compare September 22, 2026 17:02
@ylatuya

ylatuya commented Sep 22, 2026

Copy link
Copy Markdown
Contributor Author

@rsanchez87 all comments addressed.

Comment thread fluster/download_manager.py
Comment thread fluster/download_manager.py
@rsanchez87
rsanchez87 self-requested a review September 23, 2026 11:16
@dabrain34

dabrain34 commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

I see a first issue is that the download extraction is very slow in case of AV1, it seems to be due to the read of the archive which is repeated for each test vector when it could be extracted once. So I would extract everything at once to a cache and move the test vector to a secure place

@dabrain34 dabrain34 left a comment

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.

The main one is the large archive extraction

@@ -0,0 +1,446 @@
# Fluster - testing framework for decoders conformance

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.

the download manager should also provide the download patch for a given test vector which can then be used in gen_mpeg4_video.py+282

@rsanchez87 rsanchez87 Sep 29, 2026 •

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.

see #395


print("All downloads finished")

def download_test_suite(self, test_suite: Any, jobs: int) -> None:

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.

this method is unused ?

@rsanchez87 rsanchez87 Sep 29, 2026 •

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.

see #395

@@ -0,0 +1,446 @@
# Fluster - testing framework for decoders conformance
# Copyright (C) 2020, Fluendo, S.A.
# Author: Pablo Marcos Oltra <pmarcos@fluendo.com>, Fluendo, S.A.

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.

Are you Pablo is the author ? Do you think I could be added to the credits as well ?

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.

see #395

@@ -0,0 +1,446 @@
# Fluster - testing framework for decoders conformance
# Copyright (C) 2020, Fluendo, S.A.

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.

I assume its not 2020 but 2026

@rsanchez87 rsanchez87 Sep 29, 2026 •

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.

see #395

"""Path to the shared download cache directory."""
return os.path.join(self.out_dir, self.CACHE_DIR)

def download(self, test_suites: List[Any], jobs: int) -> None:

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.

do you want any here or TestSuite ?

@rsanchez87 rsanchez87 Sep 29, 2026 •

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.

see #395


for result in results:
if not result.successful():
sys.exit("Some download failed")

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.

would great to know which download failed as it can happen any time

@rsanchez87 rsanchez87 Sep 29, 2026 •

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.

see #395

suite_name: str
test_vector_name: str
input_file: str
suite_root: bool = False

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 could keep the output path here

@rsanchez87 rsanchez87 Sep 29, 2026 •

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.

see #395

if not self.keep_file and os.path.exists(cache_path):
os.remove(cache_path)

def _extract_to_suite_root(self, destination: _Destination, cache_path: str, source_filename: str) -> None:

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.

This method can be very slow in case of large archive such as the AV1 test vectors one. It can last more than 40 minutes to extract all the test vectors from the archive because it extracts (1.5s) X 3500 test vectors

@rsanchez87 rsanchez87 Sep 29, 2026 •

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.

see #395

@rsanchez87

rsanchez87 commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

I see a first issue is that the download extraction is very slow in case of AV1, it seems to be due to the read of the archive which is repeated for each test vector when it could be extracted once. So I would extract everything at once to a cache and move the test vector to a secure place

@dabrain34 agreed and good catch, each extract() call reopens the zip, so a source with N vectors means N opens. That's new vs master, which opened the archive once per suite,

Suggestion I tested: extract all zip members in a single pass (one zipfile.ZipFile open) instead of calling extract() per vector. Quick check (3000 members, 0.38 MB zip):

Approach Total
master (open once) 0.18 s
current PR (reopen per member) 16.6 s
with single-open batch 0.34 s

The download-to-cache / distribute structure stays unchanged, only the extraction loop is batched

see #395

ylatuya and others added 6 commits September 29, 2026 10:42
Download each unique source URL once for the whole selection of test
suites and distribute it to every suite that needs it, instead of
fetching shared archives once per suite. Sources are downloaded in
parallel into resources/.cache/<md5(url)>/ and the cache is removed at
the end of the run unless --keep is used.

Download orchestration moves from TestSuite into a new
fluster/download_manager.py module. TestSuite.download() remains as a
thin wrapper for the generator scripts, and --mirror support is
preserved.
Add filename_from_url() so query strings and fragments are stripped when
naming files, and use it for the download destination and the shared
download cache. Signed URLs like GCS/S3 links end with
?X-Amz-Signature=..., which broke extension checks and left odd
filenames on disk.

Ported from fluendo#338.
DownloadManager used retries**retries, so -r 5 meant 3125 download
attempts per URL before failing. download() already retries internally
with backoff; pass the user-provided count instead.

Ported from fluendo#338.
When two selected test suites share a source URL but declare different
checksums, abort instead of silently trusting whichever checksum was
seen first. Also prefer a real checksum over __skip__ when both appear
for the same URL.

Ported from fluendo#338.
If a cached archive cannot be extracted (corrupt zip/tar or gunzip
failure), delete it from the cache and report a clear error, so the next
run re-downloads it instead of failing forever. A missing archive member
is not treated as corruption and keeps the cache.

Ported from fluendo#338.
Explain that sources shared by test suites are fetched once into
resources/.cache/, that the cache is removed at the end of the run
unless --keep is used, and that concurrent download runs against the
same resources directory are not supported.

Ported from fluendo#338.
@rsanchez87
rsanchez87 force-pushed the download-dedup branch 2 times, most recently from 95eb4f3 to 73204c5 Compare September 29, 2026 08:44
@rsanchez87
rsanchez87 merged commit cda12a7 into fluendo:master Sep 29, 2026
5 checks passed
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.

3 participants