Skip to content

perf(rust): load only the encoder or decoder (encoder_only/decoder_only) - #26

Open
seo-rii wants to merge 2 commits into
feat/rust-execution-providersfrom
perf/rust-split-loading
Open

seo-rii wants to merge 2 commits into
feat/rust-execution-providersfrom
perf/rust-split-loading

Conversation

@seo-rii

@seo-rii seo-rii commented Oct 21, 2026

Copy link
Copy Markdown
Owner

Stacked on #25 (execution providers, itself on adobe#46). Review only 8ade115.

Problem

Trustmark::new always creates both the encoder and the decoder session. An embed-only or detect-only service pays for the model it never uses.

Change

  • New constructors Trustmark::encoder_only(models, variant, version, options) and Trustmark::decoder_only(models, variant, options). decoder_only takes no Version. new and with_options are unchanged.
  • Only the needed model file is read.
  • Calling the missing half returns the new Error::EncoderNotLoaded / Error::DecoderNotLoaded. encode checks for the encoder before validating the payload against a version that a decoder-only instance never received.
  • encoder_provider() / decoder_provider() now return Option<&ProviderInfo>. This changes a signature introduced, and not yet released, in the base PR.
  • These match Python's loadEncoder / loadDecoder, added in perf(python): load only the networks in use (loadEncoder/loadDecoder) #19.

Measurements

CPU, 16 cores, Q, default options. Medians of 10 fresh processes. Peak RSS is VmHWM; a process uses about 20 MiB before loading.

Mode Load Peak RSS after load First operation Peak RSS after operation
both 164 ms 141 MiB 192 ms 293 MiB
encoder only 69 ms 52 MiB 132 ms 144 MiB
decoder only 123 ms 84 MiB 80 ms 173 MiB

Tests

  • Two new model-backed tests load from a directory that holds only the one model file.
  • Locally: 31 lib tests plus 2 doctests pass. With --features cuda and no GPU, 30 pass and 3 are ignored.
  • On the A100: 33/33 pass with --include-ignored.
  • fmt, clippy -D warnings (default features and all features), cargo doc, cargo publish --dry-run --locked and MSRV 1.88 all pass.

🤖 Generated with Claude Code

Every constructor created both ONNX Runtime sessions, so a process that
only embeds or only reads watermarks still read both model files, paid
for both sessions at start-up and kept both in memory.

Add `Trustmark::encoder_only(models, variant, version, options)` and
`Trustmark::decoder_only(models, variant, options)`. They read only the
one model file and create only its session; `decoder_only` takes no
`Version` because decoding reads it from the watermark. `decode` on an
encoder-only model returns the new `Error::DecoderNotLoaded`, and
`encode` on a decoder-only model returns `Error::EncoderNotLoaded`
before the payload is checked against a version it was never given.
`encoder_provider()` and `decoder_provider()` now return `Option`, with
`None` for a session that was not loaded.

`new` and `with_options` are unchanged and still load both. Measured on
CPU (variant Q, 16-core x86-64, default options, 10 fresh processes
each, medians): loading both takes 164 ms and peaks at 141 MiB RSS
(293 MiB after one encode and decode); encoder only 69 ms / 52 MiB
(144 MiB after one encode); decoder only 123 ms / 84 MiB (173 MiB after
one decode).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 21, 2026 04:41

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

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.

2 participants