Skip to content

SOAR-0015: Add namespace file splitting proposal - #930

Open
nac5504 wants to merge 4 commits into
apple:mainfrom
nac5504:soar-0015
Open

SOAR-0015: Add namespace file splitting proposal#930
nac5504 wants to merge 4 commits into
apple:mainfrom
nac5504:soar-0015

Conversation

@nac5504

@nac5504 nac5504 commented Aug 3, 2026

Copy link
Copy Markdown

Summary

Notes

The proposal is scoped to the namespace split from PR #925: Types.swift, Types+Components.swift, and Types+Operations.swift, Types+Components+Schemas.swift, etc. More advanced sharding remains listed only as future direction.

@nac5504 nac5504 changed the title Add namespace file splitting proposal SOAR-0015: Add namespace file splitting proposal Aug 3, 2026
@nac5504
nac5504 marked this pull request as ready for review August 3, 2026 16:40

- `output.types.fileSplitting.strategy`, currently supporting `namespace`.

The same model is used by YAML configuration, direct command-line invocation, and programmatic callers that construct `_OpenAPIGeneratorCore.Config` directly.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please remove these implementation details. The design details should be about the conceptual approach and user-visible concepts.

There are many possible implementations, so no need to lock that in the proposal, in fact it can distract from where users should provide feedback - on the API and config file, not on the implementation.


#### Build-tool plugin boundary

SwiftPM and Xcode build-tool plugins must declare generated output files before invoking the generator executable. PR #925 therefore rejects build-tool plugin invocations when `output.types.fileSplitting` is configured.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hmm this is unfortunate - we should discuss more what our options are.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not being able to support this in the build plugin might actually be an argument for switching this to be the default and making this not even configurable. What do folks think?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think we should be open to moving to a prebuild plugin if it unlocks significant benefits. If we need a dynamic number of files generated then that's what prebuild plugins are advertised as the solution for.


- `Types.swift` for root declarations.
- `Types+Components.swift` for the generated `Components` namespace.
- `Types+Operations.swift` for the generated `Operations` namespace.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I wonder if we should go one level deeper - one file for #/components/schemas, one file for #/components/parameters, etc.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

This is exactly the follow-up PR I am drafting. It provides a config option to specify if you want the first-level namespaces split or the second-level.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We should discuss this more - whether and how much can actually be configurable, considering the limitation on build plugins.

#930 (comment)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

What speedup do we get from the next level. My original PoC centred around each section in components being split into its own extension, e.g. Components+Schemas.swift and Components+Parameters.swift and then further sharding these decl-wise, e.g. Components+Schemas.{0..N}.swift.

If we think there's a meaningful gain from the next level in the general case I think we just do it unilaterally. People are already opting into sharding and the fewest levers they have to pull to get maximum benefit the better. So I'd be inclined to have these phases:

  1. Shard based on namespace, but to the next level of granularity.
  2. Further shard these based on number of decls.
  3. Something more advanced.

(1) I think we could defend with few options. (2) we need to discuss as we probably need to move to a prebuild plugin.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I like 1 at the next level - out of the box, no configuration. I'm hopeful that can bring a lot of benefits already without any user action (for build plugin users; users generating manually will just need to check in a few more files).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

In earlier tests you also had the GitHub OpenAPI doc - can you test that one as well?

These outputs are typically dominated in size by Types+Components+Schemas.swift, which is why I believe the further splitting has no effect.

This is only true for OpenAPI docs that don't have much content in #/components/parameters, #/components/requestBodies, and #/components/responses. But I've definitely worked with OpenAPI docs that have quite a lot of content there, and I believe GitHub has some as well.

I'm quite surprised by the error bars showing that this change made performance worse for the Stripe API, in debug builds (where the files are compiled in parallel). How could that be? Is that just measurement noise?

@nac5504 nac5504 Aug 4, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Here is the full suite including Github's doc:
image
image
image
image

I'm quite surprised by the error bars showing that this change made performance worse for the Stripe API, in debug builds

I'm not sure which graph you're referring to here? The generator time or the swift compile time? Both splitting configs were statistically the same, the slightly longer build time for depth 2 splitting is just noise from the testing setup. In general, there could be some measurement noise since these runs exist on MacOS VMs and don't have full CPU usage, but results are averaged from 5 trials with outliers removed so it should be accurate.

@nac5504 nac5504 Aug 4, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

This is only true for OpenAPI docs that don't have much content in #/components/parameters, #/components/requestBodies, and #/components/responses. But I've definitely worked with OpenAPI docs that have quite a lot of content there, and I believe GitHub has some as well.

Looking at the size breakdown of Github's API spec, and it is still very heavily favored towards the schemas:

File LOC Size
Types+Components+Headers.swift 30 1.5 KiB
Types+Components+Parameters.swift 608 35.5 KiB
Types+Components+RequestBodies.swift 15 557 B
Types+Components+Responses.swift 717 33.9 KiB
Types+Components+Schemas.swift 323,319 20.8 MiB
Types+Components.swift 13 496 B
Types+Operations.swift 174,576 8.8 MiB
Types.swift 23,993 1.8 MiB
Total 523,271 31.4 MiB

I'd imagine a spec with lots of headers, parameters, request bodies, responses, would certainly benefit from this depth 2 sharding. I'd be in favor of making this the default config to benefit those specs also.

@nac5504 nac5504 Aug 5, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

@simonjbeaumont @czechboy0 Just to clarify before I rewrite the proposal and the implementation PR, I will update to:

  • Remove the splitting config entirely, and have the depth-2 splitting as the default
  • Add a pre-build plugin to support SwiftPM build plugin users

Is there anything else worth changing?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

  • Remove the splitting config entirely, and have the depth-2 splitting as the default

Yes.

  • Add a pre-build plugin to support SwiftPM build plugin users

No. But call it out as a potential requirement in the future directions if we were to adopt further, non-determnistic sharding.

Is there anything else worth changing?

Nah, once you've done the above I think we can kick off the forums review and have some folks chime in there.

@simonjbeaumont simonjbeaumont left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@nac5504 thanks for your work on this so far 🙏

I've kicked off the forums thread1.

Please update the status to In Review and include a link to the thread in the metadata.

Please also subscribe to the forums thread so you can engage with any feedback that might come in.

Footnotes

  1. https://forums.swift.org/t/proposal-soar-0015-namespace-based-types-file-splittingt/88830

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.

3 participants