Skip to content

feat: Allow (de)serialization of PackageGraph#583

Open
LukeMathWalker wants to merge 1 commit intoguppy-rs:mainfrom
LukeMathWalker:serde-support
Open

feat: Allow (de)serialization of PackageGraph#583
LukeMathWalker wants to merge 1 commit intoguppy-rs:mainfrom
LukeMathWalker:serde-support

Conversation

@LukeMathWalker
Copy link
Copy Markdown

Computing a PackageGraph from the "raw" output of cargo metadata can be rather expensive.
When I profiled pavex UI test suite, I found out that about ~15% of the overall CPU time was going into building PackageGraphs, since each test ends up re-building the same graph over and over again starting from a cached metadata.json file.

So, I wondered, why don't I cache PackageGraph directly? And that's how this PR came to be 😁

It adds two new optional features:

  • serde1 to the guppy crate
  • serde1 to the target-spec crate

All serde implementations are derived, with a few notable exceptions:

  • We use a manual implementation in TargetSpecExpression since Expression, from cfg_expr, doesn't implement serde's traits
  • build_targets, in PackageMetadataImpl, is serialized as a Vec of pairs in order to make its representation JSON-compatible

@LukeMathWalker LukeMathWalker force-pushed the serde-support branch 4 times, most recently from 7bf6d29 to 546280c Compare March 3, 2026 13:19
@sunshowers
Copy link
Copy Markdown
Member

Thanks for doing this. The core issue with this approach is that the internals are completely unstable and serde would effectively stabilize the internal representation. (This is why the best practice is to have two sets of types, one for serialization and one for internal representation. Today, cargo metadata is supposed to be the serialization representation.)

There is also the concern that deserializers will bypass constructor-enforced invariants unless coded and tested to not do that. If we decide to do this, I'll want to ask you to make a table of every type involved, along with whether the type has constructor-enforced invariants, and if so how the deserializer also enforces these invariants.

serde1 to the target-spec crate

See https://docs.rs/target-spec/latest/target_spec/summaries/index.html for serializable representations.

Before we do this, could you provide some performance numbers? An option here is we speed up the deserialization and parsing process -- if something shows up in a profile.

@sunshowers
Copy link
Copy Markdown
Member

Another option to speed up your test suite is that your cached fixture uses CBOR or some other more efficient format, and then you deserialize that CBOR into a CargoMetadata. Could you measure the performance of that approach?

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