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
Add a task scheduler for background indexing and preparation #1208
Conversation
@swift-ci Please test |
case suspendDependency(TaskDescription) | ||
} | ||
|
||
public protocol TaskDescriptionProtocol: Identifiable, Sendable, CustomLogStringConvertible { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd love for you to file an issue on https://github.com/apple/swift so we can enable making such a thing as TaskExecutor, rather than having to resort to trickery and unstructured tasks like this. I believe we could allow such things but today are missing pieces in the custom executors infra I think -- like querying a job for its details etc, like priority, maybe some hooks to know a job "finished" etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Filed apple/swift#73372. It’s a little vague, feel free to refine it with the things that you actually think are relevant and doable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's good, thank you -- I'll fill in the bits, and we'll figure out what is actionable :)
Sources/SKCore/TaskScheduler.swift
Outdated
/// | ||
/// Suspension might not do anything if the task has already finished, ie. even though `suspend` was called, the | ||
/// task might still | ||
func suspend() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
consider renaming the entire "suspend" wording in here; suspending is "step 1 ... ... step 2" and implies that we'll come back to a task, but this isn't that; it is "cancel and run again", like a re-schedule maybe
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call. Changed to cancelToBeRescheduled
.
Sources/SKCore/TaskScheduler.swift
Outdated
logger.debug( | ||
"Elevating priority of \(self.description.forLogging) from \(self.priority.rawValue) to \(targetPriority.rawValue)" | ||
) | ||
Task.detached(priority: targetPriority) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
probably doesn't need to detach -- plain task with priority should be fine -- and get task locals copied then
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I remember dispatch behavior this will not necessarily be 100% reliable... even if you passed highest priority it may decide to use lower I think... but the general idea is okey I suppose.
Please file an issue about an API for __priorityBoost(task, priority)
even if underscored I think we should offer this API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Filed apple/swift#73369
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall I don't have big concerns here, let's start with that and see how it works out in practice. I'm going to give it another proper read though, and we can keep polishing if we find anything.
self.suspendableTaskCreatedContinuation = suspendableTaskCreatedContinuation | ||
|
||
self.resultTask = Task.detached(priority: priority) { | ||
await withTaskGroup(of: Void.self) { taskGroup in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
consider using a discarding task group? in that the group will automatically await and since you're ignoring all failures (there's no failures) and results, the discarding group will be more efficient -- it discards tasks as soon as they complete
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don’t think that works because I need to cancel the first task in the task group (the one that is updating self.priority
) when the second task in the task group (the one that runs tasks from executionTaskCreatedStream
) finishes.
@swift-ci Please test |
@swift-ci Please test Windows |
The scheduler isn’t actually being used yet but it’s complex and generic enough that it’s possible to review it by itself.
@swift-ci Please test |
@swift-ci Please test Windows |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Heh, I was always imagining just having separate queues (and pausing when there's high priority work + not caring if there's still low priority running at the same time). But this does give us more control. May not need that much in the end, we shall see.
} | ||
}, | ||
validate: { (recordings: [Set<TaskID>]) in | ||
// Check that all high-priority tasks get executed before the low-priority tasks |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could be executing some high priority and low priority at the same time in the actual check (eg. 2 high -> high + low -> low + low would/should pass).
The scheduler isn’t actually being used yet but it’s complex and generic enough that it’s possible to review it by itself.