Skip to content

Index targets top-down instead of bottom up#2684

Open
ahoppen wants to merge 1 commit into
swiftlang:mainfrom
ahoppen:top-down-indexing
Open

Index targets top-down instead of bottom up#2684
ahoppen wants to merge 1 commit into
swiftlang:mainfrom
ahoppen:top-down-indexing

Conversation

@ahoppen

@ahoppen ahoppen commented Jun 2, 2026

Copy link
Copy Markdown
Member

We originally started preparing and indexing the low-level targets in the hope that we can unblock the files of those targets as early as possible for indexing and thus get best indexing performance. Revisiting this design decision, we can actually get a ~2x speed up (SourceKit-LSP gets indexed in 2:45 instead of 5:49 minutes on my machine) in initial indexing performance by preparing indexing top-level targets first. This speed-up is for two reasons:

  • When preparing a top-level target, all of its dependencies are implicitly also prepared. That means that we don’t need to send any prepare requests to the build server for those targets, which is very advantages for SwiftPM projects, in which the constant cost in the order of 500ms (based on my memory) even for a null build.
  • The underlying build server is able to prepare dependencies of the top-level target in parallel instead of implicitly serializing them by preparing all targets in the package in dependency order.

We originally started preparing and indexing the low-level targets in the hope that we can unblock the files of those targets as early as possible for indexing and thus get best indexing performance. Revisiting this design decision, we can actually get a ~2x speed up (SourceKit-LSP gets indexed in 2:45 instead of 5:49 minutes on my machine) in initial indexing performance by preparing indexing top-level targets first. This speed-up is for two reasons:
- When preparing a top-level target, all of its dependencies are implicitly also prepared. That means that we don’t need to send any prepare requests to the build server for those targets, which is very advantages for SwiftPM projects, in which the constant cost in the order of 500ms (based on my memory) even for a null build.
- The underlying build server is able to prepare dependencies of the top-level target in parallel instead of implicitly serializing them by preparing all targets in the package in dependency order.
var sortedTargets: [BuildTargetIdentifier] =
await orLog("Sorting targets") { try await buildServerManager.topologicalSort(of: Array(filesByTarget.keys)) }
await orLog("Sorting targets") {
try await buildServerManager.targetsSortedForIndexing(Array(filesByTarget.keys))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If batchSize is greater than 1, the targets end up being partitioned in a rather odd way. I don't believe preparationBatchingStrategy is widely used, but this change puts it in a somewhat awkward position.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Why do you think it sorts them in an odd way? It shouldn’t be any more odd than it is today, right?

@ahoppen

ahoppen commented Jun 16, 2026

Copy link
Copy Markdown
Member Author

@swift-ci Please test

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