Justified concerns about the consequences of ABI stability?

The cost of such feature is very high.

First in disk space, as it would requires to have a whole copy of all the Frameworks using Swift.

Second in RAM usage, the system will have to map all variants the frameworks instead of having a single copy.

And also in update size, as each update will have to replace all the versions of a framework. Why fixing bug for a framework using Swift 5 and not fixing it on the same framework running Swift 6 ?

1 Like

It’s high but considerably lower than the cost of all the separate copies of the Swift core libs per app that is the case today. The question is how many pure Swift frameworks there are going to be (N) and how many live versions of Swift (V) there are going to be on a phone at the same time. Admittedly that is two increasing numbers multiplied N * V i.e Quadratic which is not good in the long term but the amount of resources is only ever V times what would be used otherwise if a user has a large number of old apps. Whether old versions of frameworks would (need to) be updated is an open question. But the other side of the equation, trying to fix the ABI, has a cost too in the agility of Swift and its future reliability.

I'm concerned many developers will be caught off guard when upgrading to Swift 5 because their app suddenly again another OS versions dependency. While this probably isn't a big deal ("minimum Base SDK < Swift 5 OS requirement" alert), the expectation from past experience is that migrating to Swift 5 has no other side effects than what one might expect from migrating to previous versions.

I would think the better experience for the developer would be, at the very minimum, to opt into using Swift provided by the system. For example, changing a build setting in Xcode labelled "Links against system Swift runtime" (where other state implies the Swift runtime is bundled in the build product as it in Swift 4.2 and earlier).

I would also think the better experience for our users would be to allow the developer to opt in, as well. Improvements are made so quickly and Swift is very young. For example, crashes fixed in the compiled product between Swift 4 and 5. For another, String performance looks to be improving in leaps and abounds. Closures on the stack. Surely we'd want our users to have these with the least amount of friction as possible?

I don't think I'm alone in suggesting I'd rather spend time building features for users with the APIs out of the box made available by people much smarter than I am. Backporting or reverse engineering APIs strikes me as a luxury (or skill) many developers do not have and sure way of introducing security, performance and usability issues. Also, some platforms may not allow the inclusion of custom or updated versions of libraries like dyld.

Out of my naivety, I'm not sure I buy the argument that somehow system Swift is needed for Apple to offer Swift APIs, either. For one, there's nothing stopping them from offering a package. For another, I remember hearing (no link, sorry!) they're already statically linking Swift for the apps bundled in iOS 12 (eg: Music.app). The only real advantage to date for ABI stability I've heard is that app sizes will be smaller. I realise I'm arguing this is an acceptable cost to the consequences of the alternative.

Generally, iOS users update their devices. But business don't look at the general population for deciding to drop iOS versions. They look at their user base. Some user bases don't update very much or at all. For example, the IT departments of enterprise clients might not appreciate forking out however much it costs to pay their staff to update all their iPad kiosks to iOS whatever just so the developers can write in latest Swift. Even in terms of the general population, consider Instagram. It couldn't be optimised on iPhone XS because Xcode 10 couldn't build asset catalogs for iOS 9. Do we really want developers not to use Swift 5 so we can get products to the widest audience reasonable?

1 Like

The entire thread in Kiel’s first link is an interesting read: A case for postponing ABI stability - #46 by Chris_Lattner. It seems many of these issues were thrashed out two years ago and to an extent the arguments still apply today on both sides. I’m putting forward more of a third way that gives you the best of both worlds but it’ll be difficult to change course now. As I say, it can be adopted later if need be.

It seems entirely likely Apple can fall back to the current status quo of shipping the Swift libraries with apps in order to deploy back to older OS versions that either don't have any system Swift library or have one that's out of date. Then, due to app thinning, only users on those older OSes suffer the overhead of those libraries, and not the vast majority of users who are on the latest OS. Apple, since they're only concerned with one major version of an OS at a time, can ship their code in such a way as to work around changes in Swift, just as they do for Obj-C right now. Their libraries will be the most impacted by incompatible changes to Swift, just as they are in Obj-C (though hopefully it'll be easier for them to implement workarounds with fewer bugs in Swift). So nearly all end users win, devs won't see a different, and Apple continues their library development into Swift.

6 Likes

Thanks for writing so well what I was expecting (hoping).

I’m just speculating. I’m hoping Apple will be more forthcoming with their plans once Swift 5 ships, but who knows.

1 Like

The idea is to improve on the current situation, which is pretty bad, not to keep it the same.

For most iOS/macOS developers, the OS you ship your first version is more or less frozen for ever (or at least can not be changed for the next 4-5 years).

Compare the current Swift workflow:

  • You (or someone else) submits a bug/feature request
  • A couple months later (possibly less) it is implemented
  • A couple months later a new Swift version is released
  • You can now use this new feature (or the bug is fixed)

The time it takes from submition to actually using it is around 6 months, possibly less.

And here is what happens with an iOS/macOS SDK:

  • You submit a Radar
  • Months (possibly) years pass, without any feedback. Let's say you get lucky and it gets implemented 6 months later
  • Depending when we are on the release cycle, it can take anything from 6 to 18 months to actually get released on an OS update.
  • Unlike Apple, you can't really dump older OSes, you need to support at least 2-3 versions back, possibly more. Depending what was your original deployment version, it can be 3-4 years of waiting.

The time it takes from submission to actually using this feature is 4-5 years, possibly more.

6 Likes

It will not be possible to drop in a bundled Swift runtime once programs are compiled against the version in the OS, for a number of technical and practical reasons. In cases where we are able to backward deploy new runtime or standard library features, it will more likely look like the "arclite" mechanism for Objective-C, where a backward deployment static library is linked into the executable and used if the OS it runs on does not have that functionality in the runtime.

8 Likes

I feel that that should cover most things, shouldn't it? For example, there doesn't seem to be a reason why language-level concurrency couldn't be bridged using a shim. Would that even be a design requirement?

There is one thing we can see coming (ish) that such a mechanism couldn't accommodate: move-only types. But that will probably break half the standard library, too.

I’m not sure we should try to have old code link to a concurrent version of the standard library. Wouldn’t it be too easy for race conditions to form, since the older code wouldn’t have been designed for that?

Filed radar://47775466.

Since most Swift application development occurs with Xcode and (perhaps arguably?) on iOS, it'd be great to get an official take on the issues here, @tkremenek. The implications for (at least that subset of) the community seem enormous.

The great thing about ABI stability is that Swift libraries are going to be forwards and backwards compatible. That means that it will be technically possible to embed the Swift 9 libraries on an app deployed to macOS 10.14.4 and if you set the linker @rpaths correctly, they will be prioritized over the /usr/lib/swift/ ones.

(As a side question, what does swift-0.6 means? Currently the Xcode beta sets /usr/lib/swift-0.6/ in the @rpath, which is symlinked to /usr/lib/swift/.)

1 Like

The "0.6" is an ABI version number in case we find some terrible bug during the beta and need to break ABI. My understanding—which could be wrong—is that the libraries will be at /usr/lib/swift in the GM release.

2 Likes

This will not work, because there can only be one Swift runtime in a process, and the Apple system libraries will still be using the OS runtime.

1 Like

Technically, I think it could work.

Some options:

  • Compile all the system libraries with a LC_RPATH set to @executable_path/../Frameworks/Swift/ with more priority than /usr/lib/swift/. Then, apps with bundled Swift libraries will use them, instead of the system ones.
  • Add a new type of @rpath with could be inherited by linked libraries.
  • Some custom logic in dyld.
    ...

There are several reasons we don't want that:

  • Replacing the runtime circumvents the security of the system libraries, which are code-signed based on their using the OS version of the runtime.
  • Allowing the runtime to be replaced adds a dimension to the compatibility matrix of library code, which now must not only be concerned with OS version but Swift runtime version, putting libraries in a "DLL hell" situation.
  • The OS runtime libraries are in the dyld shared cache, so they have minimal memory and load time overhead compared to dylibs outside the shared cache.
  • The OS runtime libraries are rev-locked to the OS and so can use internal APIs and interfaces that are not stable API. Eventually it will be impossible for a runtime built outside the OS to fully replicate the behavior of the OS runtime.
3 Likes

That seems sensible. To be clear, I am OK with Swift not being back-deployable on Darwin from now on, but wanted to clarify that it could be "possible".

I am an iOS developer not really well versed on compilers so forgive my ignorance.

From the discussion above I got the impression that I will not be able to deploy an app compiled with Swift 4 to an OS that comes with a Swift 5 ABI locked standard library?

Since we will not be able to ship the runtime and standard library with the app, the app compiled with Swift 4 will not be compatible with the OS provided runtime (Swift 5). Is this correct or am I totally off?

You can still use Swift 4 mode with the Swift 5 compiler. The language version does not affect ABI. The OS version only affects the availability of standard library APIs and possibly new language features that need new runtime functionality.

4 Likes