Skip to content

Comments

Optimize Settings::from_toml() call#350

Draft
prk-Jr wants to merge 8 commits intomainfrom
feat/optimize-get_settings-call
Draft

Optimize Settings::from_toml() call#350
prk-Jr wants to merge 8 commits intomainfrom
feat/optimize-get_settings-call

Conversation

@prk-Jr
Copy link
Collaborator

@prk-Jr prk-Jr commented Feb 20, 2026

Summary

Optimize Settings::from_toml() by removing redundant config crate env var scanning at runtime. WASM guest profiling confirmed: ~4.8% → ~2.7% CPU per request.

Why this is safe

build.rs already resolves all configuration at compile time:

  1. Reads trusted-server.toml
  2. Merges TRUSTED_SERVER__* env vars via the config crate
  3. Writes the fully-resolved result to target/trusted-server-out.toml
  4. Registers cargo:rerun-if-env-changed for all possible env vars

At runtime, get_settings() loads this pre-resolved TOML via include_bytes!. The old from_toml() was re-running the entire config crate pipeline (env source scanning, config merging, deserialization) on every request — completely redundant since the embedded TOML already contains the final values. On Fastly Compute (WASM sandbox), there are no environment variables available at runtime anyway.

What changed

  • from_toml() now uses direct toml::from_str() deserialization — no config crate, no env var scanning
  • build.rs::merge_toml() now owns the env var merging logic inline using the config crate directly, instead of delegating to from_toml()
  • config crate import in settings.rs is now #[cfg(test)] — not compiled into the production binary

Why some tests use from_toml_with_env()

build.rs runs once before tests start, producing a single static target/trusted-server-out.toml. But 7 tests need to verify that different TRUSTED_SERVER__* env vars correctly override different TOML values per test (e.g., overriding publisher.origin_url in one test, integrations.prebid.bidders in another). They can't rely on build.rs for this because:

  • build.rs runs once, not per-test
  • Each test sets different env vars via temp_env that build.rs never sees
  • The resolved output file can't reflect per-test env var combinations

So these 7 tests call from_toml_with_env() directly — a #[cfg(test)] helper that preserves the original env var merging behavior. This lets them test the merging contract in isolation without going through build.rs.

All other tests (20+) use the new fast from_toml() and continue passing — they only test TOML parsing, not env var overrides.

Files changed

File Change
settings.rs from_toml()toml::from_str; added #[cfg(test)] from_toml_with_env(); config import → #[cfg(test)]
build.rs Env var merging logic moved here (was in from_toml())
Cargo.toml Added toml to [dependencies]

Test plan

  • cargo test — 352 tests pass
  • WASM build succeeds
  • WASM guest profiling confirms ~4.8% → ~2.7% CPU for get_settings()
  • Deploy to staging, run BENCH_URL=<staging> ./scripts/benchmark.sh and compare against baseline
  • Team review: verify build.rs env var merging matches original from_toml() behavior

Introduce RequestTimer for per-request phase tracking (init, backend,
process, total) exposed via Server-Timing response headers. Add
benchmark tooling with --profile mode for collecting timing data.
Document phased optimization plan covering streaming architecture,
code-level fixes, and open design questions for team review.
Introduce RequestTimer for per-request phase tracking (init, backend,
process, total) exposed via Server-Timing response headers. Add
benchmark tooling with --profile mode for collecting timing data.
Document phased optimization plan covering streaming architecture,
code-level fixes, and open design questions for team review.
RequestTimer and Server-Timing header were premature — WASM guest
profiling via profile.sh gives better per-function visibility without
runtime overhead. Also strips dead --profile mode from benchmark.sh.
build.rs already resolves trusted-server.toml + env vars at compile time
and embeds the result. Replace Settings::from_toml() with direct
toml::from_str() to skip the config crate pipeline on every request.
Profiling confirms: ~5-8% → ~3.3% CPU per request.
- OPTIMIZATION.md: profiling results, CPU breakdown, phased optimization
  plan covering streaming fixes, config crate elimination, and
  stream_to_client() architecture
- scripts/profile.sh: WASM guest profiling via --profile-guest with
  Firefox Profiler-compatible output
- scripts/benchmark.sh: TTFB analysis, cold start detection, endpoint
  latency breakdown, and load testing with save/compare support
build.rs already merges trusted-server.toml with TRUSTED_SERVER__* env
vars at compile time and embeds the resolved output. from_toml() was
re-running the entire config crate pipeline at runtime — redundant since
the embedded TOML is already fully resolved.

from_toml() now uses direct toml::from_str deserialization. Env var
merging moved to build.rs::merge_toml() where it belongs. Profiling
confirmed: ~4.8% → ~2.7% CPU per request.
@prk-Jr prk-Jr changed the title Feat/optimize get_settings call Optimize Settings::from_toml() call Feb 20, 2026
@prk-Jr prk-Jr linked an issue Feb 20, 2026 that may be closed by this pull request
@prk-Jr prk-Jr self-assigned this Feb 20, 2026
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.

Investigate and optimize get_settings() runtime overhead

1 participant