Skip to content

fix(toolkit-lib): drop the deep clone used to remove one metadata key - #1826

Merged
mrgrain merged 1 commit into
aws:mainfrom
Adityaj0:perf/refactor-digest-no-deep-clone
Aug 19, 2026
Merged

fix(toolkit-lib): drop the deep clone used to remove one metadata key#1826
mrgrain merged 1 commit into
aws:mainfrom
Adityaj0:perf/refactor-digest-no-deep-clone

Conversation

@Adityaj0

Copy link
Copy Markdown
Contributor

Fixes #1823

Reason for this change

stripConstructPath removes Metadata['aws:cdk:path'] before a resource is hashed, and does it by round-tripping the whole resource through JSON.parse(JSON.stringify(...)). The cost scales with the size of the resource rather than with the one key being removed, and every CDK-generated resource carries that key — including the large ones (inline policy documents, state machine definitions, inline Lambda code).

The clone is not needed for correctness. The result is only read: it goes straight into stripReferences, which builds its own new tree. And a RefactoringContext runs computeResourceDigests four times per environment (deployed and local stacks, in both graph directions), so each resource is cloned four times per refactor.

Description of changes

Shallow-copy the resource and its Metadata map instead:

const { 'aws:cdk:path': _, ...metadata } = resource.Metadata;
return { ...resource, Metadata: metadata };

Same output, same guarantee that the caller's template is left untouched, and the cost no longer depends on how big the resource is.

Description of how you validated changes

  • Digests are byte-identical before and after: asserted the full digest map for both graph directions against the current implementation's output on CDK-shaped templates.

  • New regression test covering the properties this relies on: metadata other than the construct path still contributes to the digest, the caller's Metadata object is not modified, and repeated calls are stable.

  • All 55 tests under test/api/refactoring/ pass.

  • Benchmark — synthetic CDK-shaped templates (nested policy documents, tags, Ref/Fn::GetAtt cross-references, DependsOn, aws:cdk:path on every resource), timing the four computeResourceDigests calls one RefactoringContext performs. Cold node process per measurement, min of 7 runs:

    template shape JSON size per side before after improvement
    1 stack × 200 resources 0.6 MiB 50.0 ms 38.1 ms 23.8%
    5 stacks × 200 resources 3.0 MiB 236.9 ms 185.2 ms 21.8%
    10 stacks × 400 resources 22.2 MiB 1534.3 ms 1140.8 ms 25.6%

Note: #1824 covers a second, larger inefficiency in the same four passes (each resource's property hash is recomputed once per graph direction). The two changes are independent and compose; this one is the smaller, self-contained half.

Checklist

  • This change contains a major version upgrade for a dependency and I confirm all breaking changes are addressed
    • Release notes for the new version:

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license

@aws-cdk-automation
aws-cdk-automation requested a review from a team August 12, 2026 08:33
@github-actions github-actions Bot added the p2 label Aug 12, 2026
auto-merge was automatically disabled August 12, 2026 08:36

Head branch was pushed to by a user without write access

@Adityaj0
Adityaj0 force-pushed the perf/refactor-digest-no-deep-clone branch from 534201d to 4c23950 Compare August 12, 2026 08:36
@Adityaj0 Adityaj0 changed the title perf(toolkit-lib): stop deep-cloning every resource to drop one metadata key refactor(toolkit-lib): drop the deep clone used to remove one metadata key Aug 12, 2026
…a key

`stripConstructPath` removes `Metadata['aws:cdk:path']` before hashing a
resource, and does it by round-tripping the whole resource through
`JSON.parse(JSON.stringify(...))`. Every CDK-generated resource carries
that key, so a refactor pays a full serialize + parse of every resource
in every stack, on both sides of the comparison, in both graph
directions.

The clone is unnecessary: the caller only reads the result, and the
single key being removed sits one level down. A shallow copy of the
resource and of its `Metadata` is enough, and keeps the caller's
template unmodified.

Measured on synthetic CDK-shaped templates (cold process, min of 7):
20-25% off the digest phase of a refactor, depending on template size.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@mrgrain
mrgrain force-pushed the perf/refactor-digest-no-deep-clone branch from 4c23950 to 57a2a19 Compare August 19, 2026 10:28
@mrgrain
mrgrain deployed to integ-approval August 19, 2026 10:29 — with GitHub Actions Active
@mrgrain mrgrain changed the title refactor(toolkit-lib): drop the deep clone used to remove one metadata key fix(toolkit-lib): drop the deep clone used to remove one metadata key Aug 19, 2026
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.91%. Comparing base (927a6cc) to head (57a2a19).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1826      +/-   ##
==========================================
- Coverage   90.92%   90.91%   -0.02%     
==========================================
  Files          80       80              
  Lines       12226    12226              
  Branches     1750     1750              
==========================================
- Hits        11117    11115       -2     
- Misses       1073     1075       +2     
  Partials       36       36              
Flag Coverage Δ
suite.unit 90.91% <ø> (-0.02%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@mrgrain
mrgrain added this pull request to the merge queue Aug 19, 2026
Merged via the queue into aws:main with commit a826ad8 Aug 19, 2026
46 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

toolkit-lib: cdk refactor deep-clones every resource to drop one metadata key (~25% of the digest phase)

3 participants