This doesn't work for priority tracking purposes, and is bad for locking 
domains too.

What you really want here is:

let groupLike : Dispatch.SomethingThatLooksLikeAGroupButDoesTracking()

myNetworkingQueue().async(group: groupLike) {
    // loadWebResource
}
myNetworkingQueue().async(group: groupLike) {
    // loadWebResource
}
groupLike.notify(myImageProcessingQueue()) {
    // decodeImage
}

The two main differences with what you explained is:

1) `groupLike` would definitely be the underlying thing that tracks 
dependencies which is required for a higher level Future-like construct (which 
async/await doesn't have to solve, provided that it captures enough context for 
the sake of such a groupLike object).

`groupLike` would likely *NOT* be an object developers would manipulate 
directly but rather the underlying mechanism.

2) the loadWebResource is done from the same serial context, because networking 
is already (if your library is sane) using an asynchronous interface that is 
very rarely a CPU bound problem, so parallelizing it is not worth it because 
synchronization cost will dominate. To give hindsight, our WWDC talk at the 
beginning pitched this measured performance win in a real life scenario:

1.3x

faster after combining queue hierarchies


This is covered here:
https://developer.apple.com/videos/play/wwdc2017/706/?time=138 
<https://developer.apple.com/videos/play/wwdc2017/706/?time=138>
https://developer.apple.com/videos/play/wwdc2017/706/?time=1500 
<https://developer.apple.com/videos/play/wwdc2017/706/?time=1500> and onward

It happens that this 30%+ performance win that we discuss here happens to have 
actually be with how some subsystems were using our networking stack, by 
recombining code that was essentially doing what you wrote into what I just 
wrote above by using the same exclusion context for all networking.

If Swift async/await leads to people writing things equivalent to using the 
global queue the way you suggest, we failed from a system performance 
perspective.

-Pierre

> On Sep 4, 2017, at 12:55 PM, Wallacy via swift-evolution 
> <swift-evolution@swift.org> wrote:
> 
> Yes, maybe in this way... Or using dispatch_group..
> 
> dispatch_group_t group = dispatch_group_create();
> 
> dispatch_group_async(group,dispatch_get_global_queue(0, 0), ^ {
>     // loadWebResource
> });
> 
> 
> dispatch_group_async(group,dispatch_get_global_queue(0, 0), ^ {
>     // loadWebResource
> });
> 
> dispatch_group_notify(group,dispatch_get_global_queue(0, 0), ^ {
>     // decodeImage ... etc...
> });
> 
> Can be made using different strategies, the compiler will select the best fit 
> for every case. Different runtimes, has different "best" strategies also. No 
> need to use a intermediary type.
> 
> Em seg, 4 de set de 2017 às 14:53, Michel Fortin <michel.for...@michelf.ca 
> <mailto:michel.for...@michelf.ca>> escreveu:
> 
> > Le 4 sept. 2017 à 10:01, Wallacy via swift-evolution 
> > <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> a écrit :
> >
> > func processImageData1a() async ->
> >  Image {
> >   let dataResource  = async loadWebResource("dataprofile.txt")
> >   let imageResource = async loadWebResource("imagedata.dat")
> >
> >   // ... other stuff can go here to cover load latency...
> >
> >   let imageTmp    = await decodeImage(dataResource, imageResource) // 
> > compiler error if await is not present.
> >   let imageResult = await dewarpAndCleanupImage(imageTmp)
> >   return imageResult
> > }
> >
> >
> > If this (or something like that) is not implemented, people will create 
> > several versions to solve the same problem, so that later (Swift 6?) will 
> > be solved (because people want this), and we will live with several bad 
> > codes to maintain.
> 
> Just to be sure of what you are proposing, am I right to assume this would be 
> compiled down to something like this?
> 
> func processImageData1a(completion: (Image) -> ()) {
>   var dataResource: Resource? = nil
>   var imageResource: Resource? = nil
>   var finishedBody = false
> 
>   func continuation() {
>     // only continue once everything is ready
>     guard finishedBody else { return }
>     guard dataResource = dataResource else { return }
>     guard imageResource = imageResource else { return }
> 
>     // everything is ready now
>     decodeImage(dataResource, imageResource) { imageTmp in
>       dewarpAndCleanupImage(imageTmp) { imageResult in
>         completion(imageResult)
>       }
>     }
>   }
> 
>   loadWebResource("dataprofile.txt") { result in
>     dataResource = result
>     continuation()
>   }
>   loadWebResource("imagedata.dat") { result in
>     imageResource = result
>     continuation()
>   }
> 
>   // ... other stuff can go here to cover load latency...
> 
>   finishedBody = true
>   continuation()
> }
> 
> 
> This seems more lightweight than a future to me. I know I've used this 
> pattern a few times. What I'm not sure about is how thrown errors would work. 
> Surely you want error handling to work when loading resources from the web.
> 
> 
> --
> Michel Fortin
> https://michelf.ca <https://michelf.ca/>
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to