[Edit December 18th: Swift Playground version - Should work on iPad with the latest Swift Playgrounds app: UKCovidData.swiftpm.zip
Note that because of the lag in local level figures by age which the app focuses on it isn't especially useful for tracking the current situation right now because the Omicron growth is so fast that week old data may be four doublings behind - maybe a factor of 16 off. It is still potentially useful for looking at the historic data and will catch up with the picture as Omicron levels off - as it must because the whole population will have had it pretty soon if current growth rates continue.]
[Edit November 10th: App link updated to fix a crash. Source code not currently updated because I can't currently participate in open source. macOS 12 is no longer in beta so it should be available to most people that way.]
A small app providing some data about case rates at the most local level available in England for particular age groups.
This app didn’t really started as planned for release (and it ended up that I couldn’t release on iOS) at least. The intention was partly to play with Swift’s structured concurrency in a real context and partly to get the UK cases data into a form where I could handle it and update it more easily than I was managing with a spreadsheet.
If you want to try the app you either need to have a Mac with macOS Monterey (12.0) which is currently only in Beta release (download app here) or to have Xcode to build and install and install it from source code on your iPhone or iPad (Github project).
Article mostly for historical record. Will try to publish an update without the inner actor stuff (no longer needed in Xcode 13 beta 5). Having written it though it seems a shame to just delete it.
In the part 1 I created an extension on AsyncSequence to return a Combine publisher representing the sequence. In this post I'm exploring the other direction wrapping a Combine publisher in an AsyncSequence. This is actually a stopgap article covering the version before the fixes in Xcode beta 5 that prevented reliably calling closures
Like the previous post the aim was substantially to learn about how these features work rather than to produce the simplest, fastest or best solution. If you really have a need for this type of operation you should probably be basing it on the AsyncStream which wraps up and simplifies a lot of the complexity. Marin Todorov has written his own pair of blog posts covering the AsyncStream approach.
With both
My solution is somewhat complicated by this bug in the interaction between actors and resuming continuations from their context. The workaround is similar to the previous post where the iterator is a class instead of an actor and owns an actor containing the state (the subscriber and the continuations). This is resolved in Xcode beta 5 so this article will very shortly be superseded with a version showing the simplified version.
This isn't necessarily described in the order I implemented this in. It was evolved with a few breaks while looking into the issues I was seeing with resuming continuations and one of the last things implemented was a change from type erasing the publisher with AnyPublisher to doing properly using generics. you can see the history if you want to see how it evolved.
The primary API we want to provide is to offer the asyncSequence on any Publisher, for now I limit to ones with an error type of Error, this could reasonably be duplicated with Never, for any other error type it would need either mapping into the non element type (some sort of Result) or mapping to an Error.
extension Publisher where Self.Failure == Error {
public var asyncSequence: PublisherAsyncSequence<Self> {
PublisherAsyncSequence(publisher: self)
}
}
The PublisherAsyncSequence itself is the next thing to define. I'll define the necessary extensions for protocol conformances afterwards.
public struct PublisherAsyncSequence<P> where P : Publisher, P.Failure == Error {
init(publisher: P) {
self.pub = publisher
}
let pub: P
public typealias Element = P.Output
public typealias Failure = P.Failure
}
Still on the public API we now need to implement the AsyncSequence protocol, which is fairly simple but leaves us with the loose end of actually implementing the real work within the iterator (which we will be making a nested class on the PublisherAsyncSequence although there are other options.
extension PublisherAsyncSequence : AsyncSequence {
public func makeAsyncIterator() -> Iterator {
let itr = Iterator()
pub.receive(subscriber: itr)
return itr
}
}
The iterator will need to conform to AsyncIterator protocol and this itself is actually fairly simple (again the bulk of the logic will be described below to do the actual work). The next() call is async so can await the real work to be done which is delegated to actor within the iterator (iActor is my variable name for innerActor)
extension PublisherAsyncSequence.Iterator : AsyncIteratorProtocol {
public typealias Element = P.Output
public func next() async throws -> Element? {
try await iActor.next()
}
}
The iterator needs to conform to Subscriber conformance so that it can pull data out of the publisher. The main detail worth noting here is that we always return a demand of .none so that the publisher won't provide another value until we ask for one. All the actual operations are done elsewhere asyncronously using `Task` (which replaces the `async` that was the initial definition in the proposal and WWDC talks) because the operations actually take place in the actor context to prevent race conditions.
In the receive(subscription:) you can see that a continuation is returned by the call to set it on the actor and then immediately called. The reason is that if next() is called on the sequence before the subscription is set up that must be made to wait. Ideally the continuation would be fired from within the actor rather than returned but due to current bugs (as of Beta3, SR-14802 and dupe that I reported) there are frequently hangs if an actor resumes a continuation.
extension PublisherAsyncSequence.Iterator : Subscriber {
public typealias Input = P.Output
public typealias Failure = P.Failure
public func receive(_ input: Element) -> Subscribers.Demand {
Task {
await receive(input: input)
}
return .none
}
public func receive(subscription: Subscription) {
Task {
let continuation = await self.iActor.setSubscription(subscription: subscription)
continuation?.resume()
}
}
public func receive(completion: Subscribers.Completion<Failure>) {
Task {
await receive(compl: completion)
}
}
}
OK the API is done with a few simple parts of the logic that call into the bulk of the actual logic.
Apologies for the switch in format but I think the gist will be easier to read for this bigger code block. This is all the private implementation of the Iterator. What I would really like would be remove the InnerIterator completely and make the Iterator and actor instead of a class but that needs to wait until the bug I mentioned is fixed.
]]>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.
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.
]]>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.
[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.
Confirmation that it is a beta 1 from someone who worked on some of the AsyncSequence stuff at Apple.
Yeah there’s a compiler bug in b1, you can use the URLSession version for now. Sorry about that
— David Smith (@Catfish_Man) June 16, 2021
(Specifically, public actors don’t get along well with library evolution mode)
— David Smith (@Catfish_Man) June 16, 2021
End update
]]>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.]
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.
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.]
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.
Update: This was all about Xcode 12 beta 1. There is probably nothing still relevant in beta 5 which includes better built in Core dat support including ways to directly bind on objects and even fetch requests so NSFetchedResultsControllers should become unnecessary. Will try to post again when I have explored further.
This might be a bit of a ramble, it certainly isn’t a carefully designed tutorial but will be a mixture of a few general early thoughts and a few minor gotchas I’ve already hit in my experimentation. I’m still in the stumbling and exploring phase and certainly haven’t mastered SwiftUI or Combine to any great degree yet. This may mean it will be helpful to few people, it is probably too heavy on the jargon if you haven’t already had a good look at SwiftUI and is too light on detail and probably inaccurate if you have gone deeply in. Certainly the shelf life of this post feels short. Feel free to let me know anywhere that I am wrong, or have missed the best documentation or give any feedback either by Twitter or in the comments.
I’m less comfortable with SwiftUI than I was with Swift itself at the similar stage 5 years ago. I believe this is going to be great but there is a mental shift required which I haven’t yet achieved.
I’m in the early stages of rewriting my first ever app (Fast Lists) to create a new version with all the toys from WWDC 2019. Including but not limited to Cloudkit Core Data syncing, SwiftUI interface, support for Mac and Watch (not just iOS as before). Multi window support. I’m also hoping to add some drag and drop support later but I haven’t even started looking at that yet. Because I’m trying everything at once my progress is a bit stop start and random at the moment but it does mean that there is normally another piece to work on if I get stuck.
This is all based on experience with Version 11.0 beta (11M336w) (the first beta) so many of these issues may be resolved very soon. In a few places I note the feedback numbers that I have raised around things that are either bugs or potential areas for improvement.
The Xcode generated NSManagedObject subclasses are annoying me. While they generate as a pair of files where you can add things to the main class and the @NSManaged variables are generated in an extension in a separate file so that they can be be overwritten and replaced as the model is updated without affecting the file where you make your changes unfortunately there is a big deficiency from my point of view in that the model type information does not get fully carried through to the Swift objects.
There are two generation options, with "Use scalar properties for primitive data types" you get usefully typed integers, floats, doubles and bools but lose the expression to express optionals/nil values. This is presumably due to the limitations of the Objective-C based API. It also expresses date types as NSTimeIntervals (Doubles) rather than NSDates. The other option will generate with objects so you will get NSDates but for number values and Booleans you will get NSNumbers which lose information about whether it is a floating point type, integer or boolean.
Just had a response to a radar (thanks Apple Swift team) that you can now implement Objective C protocols with generic Swift classes. This means that you can make typesafe and composable classes to do much of the work for many UI objects without ugly wrapping code and indirection.
This example shows a really basic example and should work in a playground.
In production code I would not initialise the table view cells in the closure but would make the closure but would probably take either the table view as an argument and directly dequeue cells from it or would take the cell as the argument and only configure it in the closure. Still this approach allows much of the boiler plate and common code to be abstracted. The next level may use a similar approach to make each section and an array of such structures could be used to make the whole table (or collection) view.
There is still work for the Swift team to do as I don't think that you can implement the Objective C protocol in an extension to a generic yet. I can't think of a reason why it wouldn't be possible and I'm confident it is coming.
Update: It should work in a protocol. I'm not sure if I'm currently doing something wrong or if it is Swift compiler bug yet:@jl_hfl You should be able to use an extension. What problem do you hit if you try?
— Joe Groff (@jckarter) September 15, 2015
I presented today at iOSDevUK in Aberystwyth with some more material on Swift Performance and how to profile Swift. Also on wrapping classes in value types. Unfortunately much of the presentation was a demo and there is no video but I'm posting the materials here and will try to make a follow up post covering some more of the details in the next week or two (no promises).
Slides (note that slides a terrible communication mechanism and caveats and subtleties in the talk may be lost):
]]>Apologies for the lack of posts, full time work and family time among other things have been keeping me from finishing off Swift performance stuff. The new Swift 2.0 features look really good but again I haven't got stuck in yet. This is a quick post about an issue concerning me since I noticed it when reading Erica Sadun's post about assertions. I actually thought it couldn't be correct when I first read it so unexpected was it but when I checked the documentation it matched exactly what Erica said.
I use assertions for things that shouldn't happen but sometimes might. For example corrupt or unprocessable network data where I write code to safely handle the case but I also want to know instantly and start debugging the issue (whether it is in the app or the server). If you do the same and have assertions which could happen then you must not build in -Ounchecked (or in Swift 2.0 with Disable Safety Checks enabled) otherwise in the event of assertions not being true you will be in undefined behaviour.
]]>Slides, video and links related to my Swift Summit talk on Swift performance. Video should be available later is now available and it might be worth watching Airspeed's talk that preceded mine before watching it when it is available I'm also expecting a blog post from him shortly on his static vs. compile time talk which is also highly relevant to optimisation.
The key point in Swift is that as the compiler gets better there is no need to choose between nice code and fast code. With a little thought and knowledge it is usually possible to get close to the speed of lowish level C code with nice abstractions. Some may say that C++ is there already but I enjoy writing Swift code much more and C++ is hampered by it's C legacy and choices made many years ago (for good reasons) from becoming a truly nice language in my view (non-Nullable by default would be hard to retrofit for example).
There were also many other excellent talks at Swift Summit, and all were at least good. I'm looking forward to watching several again.
Parsing JSON in Swift without adding libraries could be tricky and annoying at least until nil coalescing was added and optional chaining was upgraded late in the original betas but that really isn't the case at least since Swift 1.0 was final. There are clearly a wide range of JSON libraries for Swift ranging from SwiftyJSON which just tidies up extractions from deep in nested structures to Argo which will feel comfortable for those coming from Haskell and look clever but be hard to read for those not familiar with the syntax.
I want to show people that there is really nothing very tricky or ugly about parsing JSON data in Swift even without libraries to help.
This post was trigger by seeing Jameson Quave's new lightweight Luma library and the syntax in the project readme (at the time of writing) would work without a added library on the result of parsing with Cocoa's included NSJSONSerialization class. Please note that there is nothing wrong with the Luma library or anything I have seen written about it but I wanted to make clear how lightweight it is and how easy these things are to do without using a library at all.
I confirmed that the syntax was available in the Playground without using the library and there is no problem just using exactly the same syntax on the dictionary you get back from NSJSONSerialization as in the Luma example. The only difference in the presentation of printing the parsed structures.
Apple have shipped another major update (release notes - registered devs only) only two weeks after shipping the beta 1. There are major updates to Swift Playgrounds, additional syntax support for more flexible `if let`, added a zip function, various other tweaks and fixed a tonne of bugs. This is all on top of the major changes in 1.2 beta 1 that I discussed at Swift London.
Erica Sadun has already blogged about the Playgrounds and `if let` changes and I'm sure that there will be plenty more over the next week. I don't intend to go over that ground but instead discuss the performance changes in Swift 1.2 versions. [Update: I should also have mentioned Jamesson Quave's post that covers the new zip function.]
The performance jumps are very significant in Swift 1.2 and certainly in Beta 2 the steps necessary to optimise your code are significantly changed. This post will cover some information on the improvements and how to get the best out of the Swift compiler. In most cases I have encountered the performance is now very close to C/C++ code and may be faster at times.
High performance can be achieved in Xcode 6.3 beta 2 without making code changes to achieve the result that were required to get close previously. Specifically the performance gains of these changes seem to have been largely eliminated:
There also seems to have been a slight general performance gain (about 5% above beta 1 from my initial tests).
Yes. I've always believed that the language had potential to be as fast or faster than C because of strict compile time type checking, immutability and a lack of pointer aliasing concerns. With the Xcode 6.3 betas that promise is being delivered on. I'm sure the work is continuing and there is more to come but it is already fast in most cases. My thanks to the Apple team for making a fast platform but you have just taken away my ability to look impressive by speeding up code significantly with a few simple changes - you bastards.
This isn't a proper blog post but I wanted to share the slides and notes from my talk on Swift 1.2 tonight. I'll post a link when the video goes up. The video is now available here.
One thing that I forgot to mention in the talk is late initialization of let variables. The example Swift 1.2 code does show it though.
Comments, questions and suggestions all welcome.
This post is a response to David Owens' Swift Resistance Explored post.
First I want to acknowledge that Swift Debug builds are hideously slow. This isn't news to me or anyone who has seen my talk on Swift optimisation. To be clear this is a problem which Apple have said that they are working on but I still don't think it is an absolute block on any real development because there are fairly simple workarounds.
If you want to see the code under discussion it is all in my repository here with a log of my development. The first commit is the Zipfile that David made available in his blog post, the rest is my testing and development of the Swift version.
These are my performance figures (for 100 runs so it isn't directly comparable to David's):
|
Obj-C |
Swift |
Optimised |
0.077 (1.8) |
0.042 (1) |
Debug |
0.38 (9.1) |
13.7939 (327) |
[UPDATE - Swift 1.2 from Xcode 6.3 Beta 2 brings performance benefits to non-final properties and methods making final unnecessary for performance from that time - see my initial reaction to Beta 2. I still recommend final where possible as it avoids need to consider effects of an object being subclassed and methods overwritten that change the behaviour.]
This post is intended to quantify, explain and show the performance hit that you take from not adding the word final to your classes (or their properties and methods). The post was triggered by a blog post complaining about Swift performance and showing some performance figures where Swift was significantly slower than Objective-C. In the optimised builds that gap could be closed just by adding a single final keyword. I'm grateful to David Owens for showing the code he was having trouble and giving me a base to demonstrate the difference final can make without it being me cherry picking any code of my choosing.
As with most performance issues this doesn't matter most of the time. Most code is waiting on user input, network responses or other slow things and it really doesn't matter that much if the code is being accessed a few times a second. However when you have got performance critical code and in particular that inner loop that is being executed hundreds of thousands of times a second it can make a huge difference.
I've given my Beyond if let talk based on my How I Handle Optionals blog post about handling optionals in Swift twice this week. I was probably a more dynamic speaker in the NSLondon talk but the content is pretty similar. I may have been a bit slower and more methodical at the Swift London one though. Let me know if anything isn't clear in either of them or if you have any tips or suggestions (speaking or Swift).
Vimeo of talk at NSLondon. Questions from 13:30. [Updated to replace Livestream feed with this.]
When Swift's access controls were introduced I wrote about how they worked like C's with good use of internal and external headers. I've recently been asked about how to do access private properties when subclassing and thought it would be worth sharing the conversation.
If you are new to Swift's access controls I suggest you look at the previous post (same link as above) first as this is the refinement and conclusion (in my mind) of an issue that I an open question when I wrote that. If you are new to programming then this post is probably one to skip as it is more about comparing how things can be done in Swift that people are used to doing a certain way in Java than something meant as an introduction to the concepts.
I’ve a question in context of open/closed principle (Software entitles should be open for extension but closed for modification.), coming from Java, AS3 background highly influenced by the Design Patterns book by the Gang of Four, the way I see protected is so that work can be extended by other people.
How can I fully extend a class in it’s entirety without access to it’s private members, surely I can override methods but that won’t be enough.
The only way I could think is to approach this by declaring everything public or have a getter setter for each but then I’m violating “Encapsulation” principle
I believe that Swift needs one more operator to deal with optionals, in this post I present my concept to make dealing with them better and safer. It isn't a beginners introduction to optionals or Swift. There are plenty of good ones out there already.
infix operator !! { associativity right precedence 110 }
public func !!<A>(lhs:A?, rhs:@autoclosure()->A)->A {
assert(lhs != nil)
return lhs ?? rhs()
}
How this code works will be explained near the end of this post so don't feel you need to understand it now. It adds an additional operator !!
to a Swift project for dealing with optionals. It is designed to retain the benefits of strong typing proving the validity of some aspects of the code while documenting the expectation that the left hand argument will not be nil and exposing (in debug builds only) if that belief about the code is wrong.
Unlike other operators it behaves differently in a debug build than a release build. In release builds it is exactly the same as the built in ??
nil coalescing operator return the argument on the left unless it is nil in which case the right hand argument will be returned.
Swift arrays are not necessarily contiguous blocks of memory (although they may be in some cases so some code may work in some cases but not in others). Some operations may trigger them to be converted to a contiguous block of memory and I believe that is what can particularly cause issues when there is access from multiple threads.
[Update - This post is more popular than I expected (thanks Reddit). I've added some additional notes at the bottom. Also the previous post about optimisation is probably more interesting and valuable.]
Even the code as described here may not work (and I haven't tested at all) when there are multiple reads or writes that access the same elements of the array. All the code I used was either reading from a constant array (safe from multiple threads/queues) or writing into non-overlapping ranges with no reads occurring (only seems safe with the technique described here).
Swift optimisation presentation refined and developed further.
Please contact me if you want the source version and please let me know if you make use of it or find it useful.
Description of the demo from a previous event. Note that for Xcode 6.1 you will need to use the 0x, 1x, 2x and fullSpeedXC61 branches instead of the 0, 1, 2 and fullSpeed branches respectively. Likewise master currently has an Xcode 6.1 version although I will probably merge that to the real master shortly.
If you've watched the WWDC video you will already know this but if you just look at the class references it isn't obvious that . iOS 8 introduced the possibility to request permission to access location only while the App is in the foreground which should encourage users to grant permission without fear of being tracked inappropriately however the foreground only mode only works with some of the modes. This slide from the talk (WWDC 2014 What's New In Core Location - Session 706) is the key one:
I posted about the results of some experiments I had done using the iOS background modes for Bluetooth. At the time I hadn't updated any devices to iOS8 (and they would have been betas anyway). This is a quick update to confirm that there are no changes in these areas that I can see in iOS8.
If you do know of any iOS8 changes or workarounds to the issues described please let me know
Please see the previous article for discussion of the impact on on app design and some potential workarounds.
This is the Swifter Swift presentation I gave at the London Swift Meetup in Clapham today (15th September 2014). Apologies for the stock photos/standard template, I focussed on the content.
I also showed the optimisation levels as described in this blog post.
Use constants - declare with let unless avoidable, allows extra optimisation. Test before changing to mutable state within a function for performance reasons.
Currently the optimiser can do better within a particular file although this will be fixed at some point.
https://github.com/josephlord/GrayScott - Optimised version of Simon Gladwell's Cellular Automata project.
Async.legacy - My iOS7 / OS X 10.9 compatible fork.
Async - Original by Tobias Duemunk
My demo completely failed (Mac locked up when connecting to the projector) so I couldn't show what I wanted. If you want to try the demos yourself these are the Github branches I was going show. All these are 70 pixel square calculations for consistent comparison the main master branch increases in later versions.
]]>