Skip to content

Split up-to-date status tracking and index progress tracking #1322

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 21, 2024

Conversation

ahoppen
Copy link
Member

@ahoppen ahoppen commented May 21, 2024

We were mixing the up-to-date status and in-progress status of an index task in SemanticIndexManager. This meant that a single QueuedTask in the task scheduler could be needed for eg. both preparation for editor functionality in a file of that target and to re-index a file in that target. This dual ownership made it unclear, which caller would be entitled to cancel the task. Furthermore, we needed to duplicate some logic from the preparation task dependencies in SemanticIndexManager.prepare.

To simplify things:

  • Split the up-to-date status and the in-progress status into two different data structures
  • Make the caller of prepare and scheduleIndex responsible for cancellation of the task it has scheduled. TaskScheduler might receive more scheduled tasks this way but the additional tasks should all be no-ops because the status is known to be up-to-date when they execute.

We were mixing the up-to-date status and in-progress status of an index task in `SemanticIndexManager`. This meant that a single `QueuedTask` in the task scheduler could be needed for eg. both preparation for editor functionality in a file of that target and to re-index a file in that target. This dual ownership made it unclear, which caller would be entitled to cancel the task. Furthermore, we needed to duplicate some logic from the preparation task dependencies in `SemanticIndexManager.prepare`.

To simplify things:
- Split the up-to-date status and the in-progress status into two different data structures
- Make the caller of `prepare` and `scheduleIndex` responsible for cancellation of the task it has scheduled. `TaskScheduler` might receive more scheduled tasks this way but the additional tasks should all be no-ops because the status is known to be up-to-date when they execute.
@ahoppen ahoppen requested review from bnbarham and hamishknight May 21, 2024 04:44
@ahoppen ahoppen requested a review from benlangmuir as a code owner May 21, 2024 04:44
@ahoppen
Copy link
Member Author

ahoppen commented May 21, 2024

@swift-ci Please test

@ahoppen
Copy link
Member Author

ahoppen commented May 21, 2024

@swift-ci Please test Linux

@etcwilde
Copy link
Member

swiftlang/swift#73785

@swift-ci please test Linux platform

@atrick atrick merged commit 0e58ab1 into swiftlang:main May 21, 2024
2 of 3 checks passed
Copy link
Contributor

@hamishknight hamishknight left a comment

Choose a reason for hiding this comment

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

LGTM

} else {
// We couldn't determine which targets depend on the modified targets. Be conservative and assume all of them do.
preparationStatus = [:]
await indexStoreUpToDateStatus.markOutOfDate(changedFiles)
Copy link
Contributor

Choose a reason for hiding this comment

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

Isn't this already done a few lines above?

Copy link
Member Author

Choose a reason for hiding this comment

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

Indeed

Comment on lines +471 to +474
inProgressIndexTasks[file.sourceFile] = .waitingForPreparation(
preparationTaskID: preparationTaskID,
indexTask: indexTask
)
Copy link
Contributor

@hamishknight hamishknight May 22, 2024

Choose a reason for hiding this comment

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

Could we potentially run into a case?

  1. We kick off indexing for a single file
  2. We then schedule the indexing for a whole bunch of files that include that file
  3. inProgressIndexTasks gets set to the new preparation task id for the large group of files
  4. The indexing job for the single file gets completed, but that won't be reflected in inProgressIndexTasks, so inProgressIndexFiles will still list it as running
  5. We then have to wait for the large file job to complete before the file is marked as completed

And does it matter?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, we can run into that case but I don’t think it matters because the two uses of inProgressIndexFiles are:

  • Index progress reporting: The effect of this will be that the numerator of the progress will only be incremented to reflect that the single file is up-to-date only when the batch is indexed, ie. it’s lower by 1 for a little while longer. Since we’re also waiting for other files to be indexed, I don’t think it actually matters
  • Waiting for an up-to-date index: In that case we want to wait for all index tasks to finish anyway, including the batch.

@ahoppen ahoppen deleted the split-status-and-progress-tracking branch May 22, 2024 15:38
ahoppen added a commit to ahoppen/sourcekit-lsp that referenced this pull request May 22, 2024
ahoppen added a commit that referenced this pull request May 22, 2024
import SKCore

/// Keeps track of whether an item (a target or file to index) is up-to-date.
actor IndexUpToDateStatusManager<Item: Hashable> {
Copy link
Contributor

Choose a reason for hiding this comment

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

Could drop the Index? Could be OperationStatusManager? Not a huge fan of Manager though 🤔. OperationStatusTracker? 🤷

Copy link
Member Author

Choose a reason for hiding this comment

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

I think I’d like to stick with UpToDate in the name because the two states are upToDate and outOfDate. I’ll go with UpToDateTracker.

await indexStoreUpToDateStatus.markOutOfDate(changedFiles)

await preparationUpToDateStatus.markAllOutOfDate()
// `markAllOutOfDate` only marks targets out-of-date that have been indexed before. Also mark all targets with
Copy link
Contributor

Choose a reason for hiding this comment

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

markAllKnownOutOfDate?

ahoppen added a commit to ahoppen/sourcekit-lsp that referenced this pull request May 24, 2024
ahoppen added a commit to ahoppen/sourcekit-lsp that referenced this pull request May 24, 2024
ahoppen added a commit to ahoppen/sourcekit-lsp that referenced this pull request May 25, 2024
ahoppen added a commit to ahoppen/sourcekit-lsp that referenced this pull request May 25, 2024
ahoppen added a commit that referenced this pull request May 29, 2024
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.

5 participants