AsyncSequence -> Combine - equivalence (Part 1)

One of the interesting things from WWDC this year in not just that Swift is adopting AsyncSequence but that Apple is fully behind it rather than further expanding support for Combine. This raises some interesting questions for the future of Combine, whether it is just destined to be a niche feature just supporting SwiftUI in particular ways, gets completely deprecated in future. This series (possibly just pair) of blog posts is going to compare the two by means of implementing mappers in both ways between them.

[Update: Marin Todorov has a nice post about the reverse if you want to get ahead on that.] 

if you want to have

While I haven't had the opportunity to use it in a real project yet I'm really liking the look of AsyncSequence and the whole of the structured concurrency approach.

These mappers will be implemented as raw conformances because the point is for me to learn and understand more. There may be better, more efficient or simpler approaches but I want to look into the details of how they work. I'll follow up if I find significantly better ways to do it.

Resuming continuations from actors doesn't work (Beta1-2)

One thing that has delayed this post is having hit some non-deterministic bugs I lost confident in my understanding of the Structured Concurrency and didn't want to share widely until I had established that the issues I was seeing were related to Swift/MacOS bugs rather a deadlock I was introducing by doing something substantially wrong.

Swift AsyncSequence Performance Experimentation


At WWDC 2021 amongst the other async talks there was the Meet AsyncSequence talk which amongst other things demonstrated new APIs for getting async sequences of bytes from files or URLs. I was curious as to how they would perform so I did a few tests. Note that the FileHandle and URL bytes properties do not seem to be working in Xcode 13 beta 1 but the version on URLSession does seem to work and can be used for files - see the updates on my last post 

This is a very first pass with some rough numbers to get a feel for rough ballpark feeling. This is iOS 15 beta 1 (on iPhone XS) and Xcode 13 beta 1. Testing was done with -O (speed) optimisation setting. The tests themselves will be at the end of this post. I configured the tests to run just the once because first run performance was consistently slower and I thought therefore more representative of file reading where the file is not already loaded.

As a baseline I included a pure synchronous read into a Data object. The AsyncSequence approach should not get close to the performance of this as it has to do a great deal more context switching at least function calls whereas that is straight-line on a single thread code.

Results

Am I holding it wrong? - AsyncSequence file reading experiments with iOS 15 beta 1

[Update: Compiler but in Xcode 13 beta 1 confirmed. See below update]

[Update2: New post up with some rough and ready benchmarking of AsyncSequence file reading using URLSession]

So what I wanted to know was how to efficiently and asynchronously read a file into a Data object using the new structured concurrency approach in Swift. The short version is that I didn't manage to get the async approaches to file reading working, not sure yet if I was doing it wrong or there are currently problems with the frameworks (I have filed a bug report with Apple - FB9177012). Either way the async approaches were crashing for me. And I do welcome responses letting me know what I'm doing wrong.


I couldn't see any exact APIs that looked right for asynchronously reading a file. The Meet AsyncSequence talk from WWDC gave one possibility although it didn't look very efficient of handling the URL as an AsyncSequence of bytes but I thought I would do some investigation to check. I later as you can see at the end of this post realised that URLSession provides the method I need for a one shot request (that also wasn't working). I still would like to test how the performance of all these approaches varies.

Update

Confirmation that it is a beta 1 from someone who worked on some of the AsyncSequence stuff at Apple.

End update

MicroInjection - Tiny Dependency Injection Package

This is a follow up to my previous post (How does the SwiftUI Environment work and can it be used outside SwiftUI for Dependency Injection?).

Since writing that post I've refined the MicroInjection Package I created a bit. The core library is still a single file but with a couple of new features and fairly decent documentation included the file is now about 100 lines long.

[Apologies for the lack of code snippets, they are a real fiddle on Posthaven. I might move blogging to my own server at some point but I need to find time to migrate things].

[Update 20th Feb 2021: Package 1.0.0 release.]

Additional Features since Previous Post

How does the SwiftUI Environment work and can it be used outside SwiftUI for Dependency Injection?

Apologies for the lack of code syntax highlighting. I have plans to migrate my whole blog at some point in the future but I needed to get this out of my head before that. 

I woke up this morning with several questions in my head and I couldn't find an existing blog post that answered one. If one does exist let me know I'd love to compare notes.

  1. How does the SwiftUI Environment work?
  2. Can it be used outside SwiftUI for more general dependency injection?
  3. If not how similar can I make something to do the job?
  4. Why do people keep telling me the Environment is unsafe and will crash if the object requested hasn't been added?

By early evening I think I had the answers. By night the blog was written and by the early hours the Swift Package was published.

[Update 17th Feb 2021 - Follow up post now available with information about the Swift Package status.]

[Update 20th Feb 2021 - Package 1.0.0 released.]

Spoiler 1 - I Know Property Wrappers

I now have enough understanding of property wrappers to understand much but not all of what the SwiftUI environment is doing.

I didn't know Property Wrappers before this morning, beyond the concept and use of existing ones. I'm now much more familiar with them including the future extension from the Evolution proposal that seems to be live in Swift and it seems is the basis for the @Environment and @Published property wrappers.

Spoiler 2 - No it can't be used for DI but...