Skip to content

Fix unintentionally-quadratic COW copies on insertion#1626

Merged
harlanhaskins merged 6 commits intomainfrom
harlan/the-cow-jumped-over-the-moon
Mar 16, 2026
Merged

Fix unintentionally-quadratic COW copies on insertion#1626
harlanhaskins merged 6 commits intomainfrom
harlan/the-cow-jumped-over-the-moon

Conversation

@harlanhaskins
Copy link
Contributor

@harlanhaskins harlanhaskins commented Mar 13, 2026

This fixes an accidentally-quadratic COW copy of a subgraph whenever an item is inserted.

Motivation:

For large Swift Testing test suites with many parameterized test cases, we accidentally tripped this specific pathological failure mode of the graph insertion code; when we insert a new child, we mutate each graph entry along the ancestor chain. If we mutate our local copy while leaving the existing copy in the tree, it causes a COW copy of the whole tree on every insertion.

For the attached stress test, without the .take() it takes 2 seconds on my MacBook Pro, and with the .take() it takes 40 milliseconds.

Modifications:

The bulk of this fix is to .take() the child from the dictionary (Optional.take() sets the receiver to nil and returns the previous wrapped value).

This is a very similar problem and fix to this PR in swift-driver: swiftlang/swift-driver#654

Checklist:

  • Code and documentation should follow the style of the Style Guide.
  • If public symbols are renamed or modified, DocC references should be updated.

@grynspan
Copy link
Contributor

Nice. Please give me a chance to review on Monday before merging!

@stmontgomery stmontgomery added the performance 🏎️ Performance issues label Mar 13, 2026
@stmontgomery stmontgomery added this to the Swift 6.4.0 (main) milestone Mar 13, 2026
Copy link
Contributor

@jerryjrchen jerryjrchen left a comment

Choose a reason for hiding this comment

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

:shipit:

@harlanhaskins harlanhaskins force-pushed the harlan/the-cow-jumped-over-the-moon branch from d5a7f00 to e34241a Compare March 13, 2026 22:21
//

@testable import Testing
@_spi(Experimental) @_spi(ForToolsIntegrationOnly) @testable import Testing
Copy link
Contributor

Choose a reason for hiding this comment

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

Nitpick: anything experimental actually being used here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just Test.Clock, but also that doesn't need ForToolsIntegrationOnly

Copy link
Contributor

Choose a reason for hiding this comment

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

I think you have that backwards?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, turns out you only need one of the SPI tags to get the declaration. So I could pick either or leave both

@harlanhaskins harlanhaskins merged commit d077b40 into main Mar 16, 2026
27 checks passed
@harlanhaskins harlanhaskins deleted the harlan/the-cow-jumped-over-the-moon branch March 16, 2026 16:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

performance 🏎️ Performance issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants