You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: Guide.docc/IncrementalAdoption.md
-85
Original file line number
Diff line number
Diff line change
@@ -479,88 +479,3 @@ final class MyJetPack: NSJetPack {
479
479
480
480
This way Swift knows not to check for the not-correct assumption that the method requires main actor isolation.
481
481
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
-
awaitwithTaskGroup(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
-
forawait 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
-
awaitwithTaskGroup(of: Something.self) { group in
527
-
var submittedWork =0
528
-
for_in0..<maxConcurrentWorkTasks {
529
-
group.addTask { // or 'addTaskUnlessCancelled'
530
-
await lotsOfWork[submittedWork].work()
531
-
}
532
-
submittedWork +=1
533
-
}
534
-
535
-
forawait 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
-
structWork {
554
-
let dependency: Dependency
555
-
funcwork() 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