Skip to content

System resource cache - #5289

Open
JonoYang wants to merge 16 commits into
developfrom
system-resource-cache
Open

System resource cache#5289
JonoYang wants to merge 16 commits into
developfrom
system-resource-cache

Conversation

@JonoYang

@JonoYang JonoYang commented Aug 25, 2026

Copy link
Copy Markdown
Member

This PR introduces a cache for the results of scanners run by scancode. The scancode, scan_codebase, and scan_resource functions have been updated to look for cached scan results to reuse before scanning. The cache is updated after scanning, if it was required.

This is related to #3941 #4556

Comment thread src/scancode/results_cache.py Dismissed
Comment thread src/scancode/results_cache.py Dismissed
Comment thread src/scancode/results_cache.py Dismissed
Comment thread src/scancode/results_cache.py Dismissed
Comment thread tests/scancode/test_results_cache.py Dismissed
Signed-off-by: Jono Yang <jyang@nexb.com>
    * Use sha256 instead of md5

Signed-off-by: Jono Yang <jyang@nexb.com>
Signed-off-by: Jono Yang <jyang@nexb.com>
Signed-off-by: Jono Yang <jyang@nexb.com>
    * Create envvar for controlling whether or not the scan results cache is used

Signed-off-by: Jono Yang <jyang@nexb.com>
Signed-off-by: Jono Yang <jyang@nexb.com>
Signed-off-by: Jono Yang <jyang@nexb.com>
Signed-off-by: Jono Yang <jyang@nexb.com>
Signed-off-by: Jono Yang <jyang@nexb.com>
Signed-off-by: Jono Yang <jyang@nexb.com>
Signed-off-by: Jono Yang <jyang@nexb.com>
Signed-off-by: Jono Yang <jyang@nexb.com>
Signed-off-by: Jono Yang <jyang@nexb.com>
@JonoYang
JonoYang force-pushed the system-resource-cache branch from a1aa058 to 60ee685 Compare August 28, 2026 23:43
Signed-off-by: Jono Yang <jyang@nexb.com>
Signed-off-by: Jono Yang <jyang@nexb.com>
@JonoYang
JonoYang force-pushed the system-resource-cache branch from e965307 to 1247f39 Compare September 3, 2026 23:25
    * The runner cannot instantiate a cryptography library of some kind

Signed-off-by: Jono Yang <jyang@nexb.com>

@AyanSinhaMahapatra AyanSinhaMahapatra left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@JonoYang LGTM! Thanks++
See some of my comments for your consideration.
I also did some basic scans which shows negligible performance impact on cache creation and significant performance gain from using cached results. But we should probably do some proper benchmarks to test the performance gains too.

The archives I used for running the benchmarks:

First scan of v2.1.2 without --use-cached-results:

 scancode -clipeu syncthing-2.1.2.tar.gz-extract/  --json-pp syncthing-2.1.2-clipeu.json -n 6
Setup plugins...
Collect file inventory...
Scan files for: info, packages, licenses, copyrights, emails, urls with 6 process(es)...
[####################] 1868
Scanning done.
Summary:        info, packages, licenses, copyrights, emails, urls with 6 process(es)
Errors count:   0
Scan Speed:     7.71 files/sec. 110.88 KB/sec.--use-cached-results
Initial counts: 1133 resource(s): 934 file(s) and 199 directorie(s)
Final counts:   1133 resource(s): 934 file(s) and 199 directorie(s) for 13.11 MB
Timings:
  scan_start: 2026-09-07T100805.133779
  scan_end:   2026-09-07T101008.901230
  setup_scan:licenses: 2.45s
  setup: 2.45s
  inventory: 0.11s
  scan:packages: 0.13s
  scan: 121.10s
  output:json-pp: 0.34s
  output: 0.34s
  total: 124.13s
Removing temporary files...done.

First scan of v2.1.3 without --use-cached-results:

scancode -clipeu syncthing-2.1.3.tar.gz-extract/  --json-pp syncthing-2.1.3-clipeu.json -n 6
Setup plugins...
Collect file inventory...
Scan files for: info, packages, licenses, copyrights, emails, urls with 6 process(es)...
[####################] 1866
Scanning done.
Summary:        info, packages, licenses, copyrights, emails, urls with 6 process(es)
Errors count:   0
Scan Speed:     7.40 files/sec. 106.58 KB/sec.
Initial counts: 1132 resource(s): 933 file(s) and 199 directorie(s)
Final counts:   1132 resource(s): 933 file(s) and 199 directorie(s) for 13.12 MB
Timings:
  scan_start: 2026-09-07T101019.832652
  scan_end:   2026-09-07T101228.601000
  setup_scan:licenses: 2.47s
  setup: 2.47s
  inventory: 0.11s
  scan:packages: 0.11s
  scan: 126.07s
  output:json-pp: 0.32s
  output: 0.32s
  total: 129.11s

Scan of v2.1.2 with --use-cached-results (only creating cache):

scancode -clipeu syncthing-2.1.2.tar.gz-extract/  --json-pp syncthing-2.1.2-clipeu.json -n 6 --use-cached-results
Setup plugins...
Collect file inventory...
Scan files for: info, packages, licenses, copyrights, emails, urls with 6 process(es)...
[####################] 1868
Scanning done.
Summary:        info, packages, licenses, copyrights, emails, urls with 6 process(es)
Errors count:   0
Scan Speed:     7.70 files/sec. 110.63 KB/sec.
Initial counts: 1133 resource(s): 934 file(s) and 199 directorie(s)
Final counts:   1133 resource(s): 934 file(s) and 199 directorie(s) for 13.11 MB
Timings:
  scan_start: 2026-09-07T101433.426523
  scan_end:   2026-09-07T101637.529302
  setup_scan:licenses: 2.49s
  setup: 2.49s
  inventory: 0.12s
  scan:packages: 0.12s
  scan: 121.38s
  output:json-pp: 0.34s
  output: 0.34s
  total: 124.46s
Removing temporary files...done.

Scan of v2.1.3 with --use-cached-results (using cached results on another version with highly similar files):

scancode -clipeu syncthing-2.1.3.tar.gz-extract/  --json-pp syncthing-2.1.3-clipeu.json -n 6 --use-cached-results
Setup plugins...
Collect file inventory...
Scan files for: info, packages, licenses, copyrights, emails, urls with 6 process(es)...
[####################] 1866
Scanning done.
Summary:        info, packages, licenses, copyrights, emails, urls with 6 process(es)
Errors count:   0
Scan Speed:     45.50 files/sec. 655.31 KB/sec.
Initial counts: 1132 resource(s): 933 file(s) and 199 directorie(s)
Final counts:   1132 resource(s): 933 file(s) and 199 directorie(s) for 13.12 MB
Timings:
  scan_start: 2026-09-07T102406.378978
  scan_end:   2026-09-07T102429.571458
  setup_scan:licenses: 2.45s
  setup: 2.46s
  inventory: 0.11s
  scan:packages: 0.13s
  scan: 20.50s
  output:json-pp: 0.33s
  output: 0.33s
  total: 23.55s
Removing temporary files...done.

Scan of v2.1.2 with --use-cached-results (using cached results on a same version with exactly similar files):

scancode -clipeu syncthing-2.1.2.tar.gz-extract/  --json-pp syncthing-2.1.2-clipeu.json -n 6 --use-cached-results
Setup plugins...
Collect file inventory...
Scan files for: info, packages, licenses, copyrights, emails, urls with 6 process(es)...
[####################] 1868
Scanning done.
Summary:        info, packages, licenses, copyrights, emails, urls with 6 process(es)
Errors count:   0
Scan Speed:     1563.51 files/sec. 21.95 MB/sec.
Initial counts: 1133 resource(s): 934 file(s) and 199 directorie(s)
Final counts:   1133 resource(s): 934 file(s) and 199 directorie(s) for 13.11 MB
Timings:
  scan_start: 2026-09-07T102440.089470
  scan_end:   2026-09-07T102443.410571
  setup_scan:licenses: 2.50s
  setup: 2.50s
  inventory: 0.11s
  scan:packages: 0.13s
  scan: 0.60s
  output:json-pp: 0.33s
  output: 0.33s
  total: 3.67s
Removing temporary files...done.

Summary:

  • scan of v2.1.2: 124.13s
  • scan of v2.1.3: 129.11s
  • scan of v2.1.2 only creating cache: 124.46s (negligible difference)
  • scan of v2.1.3, using cached results on another version with highly similar files: 23.55s
  • scan of v2.1.2, using cached results on a same version with exactly similar files: 3.67s

return hasher


def compute_results_cache_index(location, filename):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can this be reused from functions in commoncode.hash? The code there was updated to work on chunks a while ago too.


def get_results_cache_directory_location(results_cache_index, results_cache_dir=results_cache_dir):
"""
Return the location of the directory containing the cache files for a given

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Should we include an example results_cache_index string in the docstring?

When run as a stand-alone release, the results cache is tied to specific
ScanCode toolkit versions. When run in development mode, the cache is stored
in the `scancode-toolkit/.cache` directory.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Should we include some functionality to re-compute the cache for a file based on data structure changes caused by different versions of scancode, or different CLI options used with different output data formats? There is some discussion on this at #3941

We need to check that we atleast handle the errors resulting out of this. Additionally it would be nice to somehow include the data format versions in the index cache too, smartly avoiding cache recompute whenever possible.

Output data formats are not always changes based on scancode versions, and an update in the output data format version also doesn't correspond to updates in all the scanner output data. So we need to probably compute a hash based on all the data fields present for a particular scanner data based on the keys present in the mapping and include this in the index file path? This would cover both variations caused by scancode version changes and CLI options used.

This is an enhancement though, so feel free to mark this out of scope.

Comment thread src/scancode/cli.py
@click.option('--use-cached-results',
is_flag=True,
default=False,
hidden=True,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We could leave this as-is and not hidden, as there is an EXPERIMENTAL tag in the help text already. We want more people to see and test out the functionality probably, what do you think?

Comment thread src/scancode/cli.py
hidden=True,
help_group=cliutils.MISC_GROUP, sort_order=1000, cls=PluggableCommandLineOption)

@click.option('--use-cached-results',

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Was just wondering if this is the best name since this option enables both the creation of the cache and the use of cached results and this name only indicates the latter.

Alternatives could be: --use-results-cache, --cache-results, --cache but I'm not sure what to choose too.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

One other option is to use two other options one to create the cache and the other to use the cached results, but using just one option is probably much better if there are no large performance implications.

Comment thread src/scancode/cli.py
is_flag=True,
default=False,
hidden=True,
help='(EXPERIMENTAL) ScanCode will use cached results during scan time.',

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We need to highlight in the help text also that this option both:

  • caches scan results from scans
  • uses cached scan results

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