Skip to content

Cache parsed configuration files to avoid redundant reads on startup (#59807)#69779

Open
ggiesen wants to merge 1 commit into
saltstack:3006.xfrom
ggiesen:fix-59807-config-cache
Open

Cache parsed configuration files to avoid redundant reads on startup (#59807)#69779
ggiesen wants to merge 1 commit into
saltstack:3006.xfrom
ggiesen:fix-59807-config-cache

Conversation

@ggiesen

@ggiesen ggiesen commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Caches parsed configuration files so a given file is read and parsed from disk once while it is unchanged, instead of on every master_config/minion_config/client_config call.

What issues does this PR fix or reference?

Fixes #59807

Previous Behavior

salt.config._read_conf_file re-read and re-parsed the configuration file from disk on every call. During daemon startup the same file is loaded many times: each MasterMinion and LocalClient built by _load_modules, across every forked subprocess (Maintenance, MWorkers, ReqServer, ...), calls back through master_config/minion_config -> load_config -> _read_conf_file. Measured on 3006 with a trivial master config, the file was openat()ed 84 times during startup (across 8 processes); the reporter saw 646 with a gitfs/ext_pillar config.

New Behavior

_read_conf_file caches the parsed result keyed by the file's (st_mtime_ns, st_size) and returns a deep copy to each caller. Unchanged files are served from the cache; a changed file (for example a reload) has a different mtime or size and is re-read. The deep copy means callers that mutate the returned opts cannot corrupt the cached copy. With this change the same trivial-config startup reads the file once (84 -> 1), and the master boots and generates its keys normally.

Verified:

  • openat() count for the config file drops from 84 to 1 across a full salt-master startup (strace).
  • Returned opts match the file contents; repeated calls return equal but distinct objects; mutating one does not affect the next.
  • A file changed on disk is re-read (new size/mtime).
  • tests/unit/test_config.py still passes (76 passed, 7 skipped); new tests added.

Merge requirements satisfied?

  • Docs - n/a
  • Changelog - changelog/59807.fixed.md
  • Tests written/updated - tests/pytests/unit/config/test_conf_file_cache.py (the parse-once test fails without this change)

Commits signed with GPG?

No

Every master_config/minion_config/client_config call re-read and re-parsed the
configuration file from disk. During master startup this happens many times per
process across all forked subprocesses -- a trivial config was read 84 times,
and configs with gitfs/ext_pillar remotes far more (the reporter saw 646).

Cache the parsed result in _read_conf_file, keyed by the file's mtime and size,
and hand callers a deep copy so they cannot corrupt the cache. A changed file
(reload) is re-read. This reduces the trivial-config startup read count from 84
to 1.

Fixes saltstack#59807
@ggiesen ggiesen requested a review from a team as a code owner July 11, 2026 15:36
@dwoz dwoz added the test:full Run the full test suite label Jul 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

test:full Run the full test suite

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants