Skip to content

Commit df4c36f

Browse files
authored
Merge pull request #139 from apple/ktoso-patch-1
2 parents 3eb445c + 3fb34c8 commit df4c36f

File tree

1 file changed

+0
-85
lines changed

1 file changed

+0
-85
lines changed

Guide.docc/IncrementalAdoption.md

-85
Original file line numberDiff line numberDiff line change
@@ -479,88 +479,3 @@ final class MyJetPack: NSJetPack {
479479

480480
This way Swift knows not to check for the not-correct assumption that the method requires main actor isolation.
481481

482-
## Dispatch
483-
484-
Some patterns which you may be used to from Dispatch or other concurrency libraries
485-
may need to be re-shaped in order to fit the world of Swift's structured concurrency model.
486-
487-
### Limiting concurrency using Task Groups
488-
489-
Sometimes you may find yourself with a large list of work to be processed.
490-
491-
While it is possible to just enqueue "all" those work items to a task group like this:
492-
493-
```swift
494-
// WARNING: Potentially wasteful -- perhaps this creates thousands of tasks concurrently (?!)
495-
496-
let lotsOfWork: [Work] = ...
497-
await withTaskGroup(of: Something.self) { group in
498-
for work in lotsOfWork {
499-
// WARNING: If this is thousands of items, we may end up creating a lot of tasks
500-
// which won't get to be executed until much later, as we have a global limit on
501-
// the amount of concurrently running tasks - depending on the core count of the system,
502-
// and the default global executor's configuration.
503-
group.addTask {
504-
await work.work()
505-
}
506-
}
507-
508-
for await result in group {
509-
process(result) // process the result somehow, depends on your needs
510-
}
511-
}
512-
```
513-
514-
If you suspect you may be dealing with hundreds or thousands of items, it may be wasteful to enqueue them all immediately.
515-
Creating a task (in `addTask`) needs to allocate some memory for the task in order to suspend and execute,
516-
while this amount of memory isn't too large, it can become significant if creating thousands of tasks which don't get to
517-
execute immediately but are just waiting until the executor gets to run them.
518-
519-
When faced with such a situation, it may be beneficial to manually throttle the number of concurrently added tasks to the task group, as follows:
520-
521-
```swift
522-
let lotsOfWork: [Work] = ...
523-
let maxConcurrentWorkTasks = min(lotsOfWork.count, 10)
524-
assert(maxConcurrentWorkTasks > 0)
525-
526-
await withTaskGroup(of: Something.self) { group in
527-
var submittedWork = 0
528-
for _ in 0..<maxConcurrentWorkTasks {
529-
group.addTask { // or 'addTaskUnlessCancelled'
530-
await lotsOfWork[submittedWork].work()
531-
}
532-
submittedWork += 1
533-
}
534-
535-
for await result in group {
536-
process(result) // process the result somehow, depends on your needs
537-
538-
// Every time we get a result back, check if there's more work we should submit and do so
539-
if submittedWork < lotsOfWork.count,
540-
let remainingWorkItem = lotsOfWork[submittedWork] {
541-
group.addTask { // or 'addTaskUnlessCancelled'
542-
await remainingWorkItem.work()
543-
}
544-
submittedWork += 1
545-
}
546-
}
547-
}
548-
```
549-
550-
If the "work" task involves long-running synchronous code it may make sense to voluntarily suspend the task and allow other tasks to execute:
551-
552-
```swift
553-
struct Work {
554-
let dependency: Dependency
555-
func work() async {
556-
await dependency.fetch()
557-
// execute part of long running synchronous code
558-
await Task.yield() // explicitly insert a suspension point
559-
// continue long running synchronous execution
560-
}
561-
}
562-
```
563-
564-
Introducing an explicit suspension point helps Swift balance between making progress on this task, and letting other tasks in your program make progress on their work.
565-
However, if this task has the highest-priority in the system, the executor immediately resumes execution of the same task.
566-
Therefore an explicit suspension point isn’t necessarily a way to avoid resource starvation.

0 commit comments

Comments
 (0)