web: reuse the parsed web configuration while the file is unchanged - #443
Open
mrueg wants to merge 1 commit into
Open
web: reuse the parsed web configuration while the file is unchanged#443mrueg wants to merge 1 commit into
mrueg wants to merge 1 commit into
Conversation
The configuration file is consulted on every http request so that changes are picked up without a restart. That read was an os.ReadFile plus a strict YAML unmarshal plus header validation, every time, and it happens on the scrape path as well as on every TLS handshake through GetConfigForClient. It was by far the most expensive part of serving a request: measured against the handler it wraps, the toolkit's handler cost 15.9us per request where the wrapped handler cost 0.87us. Keep the parsed configuration and reuse it while the file's modification time and size are both unchanged, replacing a read and a parse with a stat in the common case. BenchmarkGetConfig 14743 ns/op 7515 B/op 64 allocs/op # before BenchmarkGetConfig 1160 ns/op 515 B/op 3 allocs/op # after An edit is still picked up on the next request, which the existing TestConfigReloading continues to cover. The limitation worth being explicit about is that a write leaving both the modification time and the size identical is not noticed. On a filesystem whose timestamps have sub-second resolution that needs a rewrite within the same nanosecond at exactly the same length; where timestamps have one second resolution the window is a second. There is a test that pins this behaviour so it is not discovered by accident later. Failures are not cached, so a file that does not parse is reported on every request until it is fixed rather than once. Callers get a copy of the configuration struct, so one caller cannot change what the next one sees; the maps inside are shared and are only ever read. Certificates are still loaded from disk on every handshake. Caching those is a separate change and is deliberately not part of this one. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Manuel Rüger <manuel@rueg.eu>
mrueg
force-pushed
the
perf/cache-parsed-web-config
branch
from
September 2, 2026 13:44
6d9029f to
6f2be48
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The configuration file is consulted on every http request so that changes are picked up without a restart. That read is an
os.ReadFileplus a strict YAML unmarshal plus header validation, every time — on the scrape path, and on every TLS handshake throughGetConfigForClient.It is by far the most expensive part of serving a request. Measured against the handler it wraps: the toolkit's handler cost 15.9µs/request where the wrapped handler cost 0.87µs.
Change
Keep the parsed configuration and reuse it while the file's modification time and size are both unchanged, replacing a read and a parse with a
statin the common case.The tradeoff, stated plainly
An edit is still picked up on the next request, and the existing
TestConfigReloadingcontinues to cover that. The limitation worth being explicit about is that a write leaving both the modification time and the size identical is not noticed. On a filesystem whose timestamps have sub-second resolution that needs a rewrite within the same nanosecond at exactly the same length; where timestamps have one-second resolution the window is a second.I have added a test that pins this behaviour so it is documented rather than discovered later. If you would rather not accept that window at all, this one is easy to drop — the other PRs in this batch do not depend on it.
Details
Configstruct, so one caller cannot change what the next sees. The maps inside are shared and only ever read.🤖 Generated with Claude Code