<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">Hi Xiaodi,<div class=""><br class=""></div><div class="">It’s an interesting suggestion. &nbsp;My inclination is that seeding prototype APIs would be better done via source package managers, and not as binary frameworks. &nbsp;But they are two different approaches to the same problem and it is an interesting idea.</div><div class=""><br class=""></div><div class="">I’d like to first focus, however, on the utility of having such a separate dylib for the purposes of sunsetting APIs.</div><div class=""><br class=""></div><div class="">Ted<br class=""><div><br class=""><blockquote type="cite" class=""><div class="">On Jan 12, 2018, at 6:02 PM, Xiaodi Wu &lt;<a href="mailto:xiaodi.wu@gmail.com" class="">xiaodi.wu@gmail.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class="">One point to bring up is that what you call libswiftCoreDeprecated.dylib can be the place that future APIs live until they’re sufficiently mature.<br class=""><br class="">I highly doubt that additions to the Swift standard library past 5.0 will all be fully baked on arrival, and having everything carved into stone the moment it’s added seems unwise.<br class=""><br class="">Against this consideration the benefit of enabling a more stable set and a less stable set of APIs seems to outweigh the start-up time consideration.  Yes, the implication is that most Swift apps will have to incur an increased runtime cost.<br class=""><div class="gmail_quote"><div dir="ltr" class="">On Fri, Jan 12, 2018 at 18:43 Ted Kremenek via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:<br class=""></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word;line-break:after-white-space" class="">Hi Chris,<div class=""><br class=""></div><div class="">Instead of responding to each of your point bit-by-bit, I’ll try a different tactic to explain my reasoning — which may be wrong — by explaining how I see things top down with the tradeoffs they incur.&nbsp; I’m going to say a bunch of things I know *you* know, but others are on this thread and I’ll state things for end-to-end clarity.</div><div class=""><br class=""></div><div class="">It seems to me that we are talking about two possible scenarios: (1) the status quo of keeping everything in libswiftCore.dylib or (2) splitting libswiftCore.dylib into two dylibs, one which includes some of the “deprecated” APIs.&nbsp; I’ll enumerate what I think are the tradeoffs/benefits we will see with both scenarios, and see where the mismatch in our “talking past each other” is happening.</div><div class=""><br class=""></div><div class=""><div class="">In both cases (A) and (B), with ABI stability the Standard Library has the option to ship in the OS.&nbsp; Thus applications using Swift on (say) iOS would no longer need to include libswiftCore.dylib in the app when running on an OS that shipped with the Standard Library.</div></div><div class=""><br class=""></div><div class="">With that in mind, here are the tradeoffs as I see between scenarios (A) and (B):</div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">(A) Status quo: Keep shipping everything in libswiftCore.dylib</div><div class=""><br class=""></div><div class="">- Applications running on an OS with the Standard Library would no longer have *any* of the currently libswift*.dylib’s embedded inside the application bundle because they would just use the one in the OS.</div><div class=""><br class=""></div><div class="">- One benefit of using libswift*.dylibs in the OS as opposed to those embedded inside the app bundle is that there is a non-neglible startup time improvement, as the code signing verification that happens when an app launches would be faster as it would not need to verify each of these dylibs that were previously embedded in the app.&nbsp; We should consider this the new baseline for app startup time for an app running on an OS with an ABI stable Standard Library.</div><div class=""><br class=""></div><div class="">- We continue to support the deprecated APIs for some time, possibly indefinitely, even when better alternatives come around.</div><div class=""><br class=""></div><div class="">(B) Split libswiftCore.dylib into two dylibs, one that gets embedded in the app bundle</div><div class=""><br class=""></div><div class="">In the second scenario, we split out the deprecated APIs into a separate dylib, say libswiftCoreDeprecated.dylib.&nbsp; That solution would have the following characteristics:</div><div class=""><br class=""></div><div class="">- Like scenario (A), app bundles would not need to embed libswiftCore.dylib when running on an OS that had an ABI-stable Standard Library.</div><div class=""><br class=""></div><div class="">- Compared to scenario (A), the OS shipping the Standard Library would have a slightly smaller libswiftCore.dylib that didn’t carry the bits for the deprecated APIs.&nbsp; This would be a benefit in the code size for the OS, but not for the app itself.</div><div class=""><br class=""></div><div class="">- Any app using a deprecated API we put into libswiftCoreDeprecated.dylib (e.g., Mirrors) would need to embed libswiftCoreDeprecated.dylib inside their app bundle.&nbsp; Compared to the new baseline I mentioned in (A), such apps would have a launch time regression once they started using any API in the libSwiftCoreDeprecated.dylib because code signing would need to verify the dylib, just like it does today with the libswiftCore.dylib that is embedded in every application.&nbsp; They would also be slightly larger because the app bundle has the burden of hosting libswiftCoreDeprecated.dylib, instead of compared to scenario (A) where the implementations of the deprecated APIs are hosted by the libswiftCore.dylib that ships in the OS.</div><div class=""><br class=""></div><div class="">- Because of binary compatibility concerns, after Swift 5 we would *never* be able to “take out” any further APIs from libswiftCore.dylib and put them in libswiftCoreDeprecated.dylib.&nbsp; This factorization can only happen once.</div><div class=""><br class=""></div><div class="">- There is some slight additional complexity added to the compiler and build system to support this spit of the Standard Library into multiple dylibs.&nbsp; It’s not a huge concern but it does exist and it is not free both in terms of implementing and maintaining.</div><div class=""><br class=""></div><div class="">- We continue to support the deprecated APIs for some time, possibly indefinitely, even when better alternatives come around.&nbsp; We *may* be able to completely sunset these APIs by having a future version of the Swift compiler simply refuse to build projects that use the deprecated (now obsoleted) APIs.&nbsp; At that point, these apps need to move to using the newer API alternatives, or not upgrade to using a new Swift compiler.</div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">With these points in mind, both scenarios are (by construction) very similar.&nbsp; Scenario (B) potentially provides a bit more flexibility in outright sunsetting deprecated APIs down the road — but only the APIs we deem today should be on that path. In the future when we decide to deprecate APIs in the Standard Library we will need to follow the same kind of deprecation-and-obsoletion path as other binary frameworks in macOS/iOS, which may mean keeping API implementations around for a very long time just for the purpose of binary compatibility.</div><div class=""><br class=""></div><div class="">If you agree with me up to this point, to me this boils down to a tradeoff of some slightly increased opportunity to sunset some APIs in the future for a slight reduction in size of the Standard Library today (as it ships in the OS).&nbsp; Most apps that don’t use these APIs won’t care either way, because even if we go with scenario B if they don’t use one of the deprecated APIs they will essentially be in scenario A (and thus get the benefit of using a Standard Library from the OS).&nbsp; In scenario B, those apps that use the deprecated APIs will be slightly punished with slightly increased app bundle size and startup time.&nbsp; Further, these APIs really can’t be deprecated right now (in terms of marking them deprecated in the module) until we have actual alternatives, so for the users that really want to use Mirrors today (which I agree may be small) that is the main tool they have to obtain that functionality.&nbsp; Such users will pay a cost — albeit probably pretty minor — in scenario B.</div><div class=""><br class=""></div><div class="">I have not done the measurements of the impact in code size to the Standard Library of removing Mirrors, but I hypothesize it is relatively modest (I will look at verifying this hypothesis).</div><div class=""><br class=""></div><div class="">Do these observations align with what you are proposing, or am I missing a critical detail?</div></div><div style="word-wrap:break-word;line-break:after-white-space" class=""><div class=""><br class=""></div><div class="">Ted</div></div><div style="word-wrap:break-word;line-break:after-white-space" class=""><div class=""><div class=""><br class=""><blockquote type="cite" class=""><div class="">On Jan 11, 2018, at 11:56 AM, Chris Lattner &lt;<a href="mailto:clattner@nondot.org" target="_blank" class="">clattner@nondot.org</a>&gt; wrote:</div><br class="m_4719157997125806949Apple-interchange-newline"><div class=""><div style="word-wrap:break-word" class=""><div class=""><blockquote type="cite" class=""><div class="">On Jan 11, 2018, at 12:01 AM, Ted Kremenek &lt;<a href="mailto:kremenek@apple.com" target="_blank" class="">kremenek@apple.com</a>&gt; wrote:</div><div class=""><div style="word-wrap:break-word;line-break:after-white-space" class=""><div class=""><blockquote type="cite" class=""><div class=""><span style="font-family:Helvetica;font-size:14px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline!important" class="">The nice thing about this is that only people who use these things would have to pay the cost, and you can directly message this by deprecating all the stuff in it.&nbsp; Think about it as an overlay for the Swift standard library :-)</span></div></blockquote></div><br class=""><div class="">Hi Chris,</div><div class=""><br class=""></div><div class="">Even if we split the APIs into two sets, with an “ABI unstable” subset, we are still going to “carry round these ’suboptimal APIs’” because clients are using them today and those APIs — without an active plan to remove them — *are* a part of the Standard Library.&nbsp; We’ve past the point in Swift where we can just rip them out (you said so yourself in a follow up email).</div></div></div></blockquote><div class=""><br class=""></div><div class="">Who is “we” and how do you define carry?</div><div class=""><br class=""></div><div class="">I think you’re saying that they will remain part of the swift project (in the “SwiftDeprecated” module) for effectively ever.&nbsp; If so, I agree, and that’s the point.&nbsp; The point is that the code can continue to exist and service the few people who need it (and will become even fewer over the years) without causing *harm* to the Swift ecosystem over the near or long term.&nbsp; That’s the feature.</div><div class=""><br class=""></div><blockquote type="cite" class=""><div class=""><div style="word-wrap:break-word;line-break:after-white-space" class=""><div class="">It feels to me that the main advantage of the overlay is a solution to remove out pieces of the Standard Library that will be used in practice less, and thus clients don’t “pay the cost” when they don’t use them. </div></div></div></blockquote><div class=""><br class=""></div><div class="">Yes, exactly.</div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap:break-word;line-break:after-white-space" class=""><div class="">But I think we should be honest about what that “cost” actually is, as these APIs aren’t going away right now.&nbsp; These suboptimal APIs will stay around at least until better ones are created, and even then some existing clients will want to rely on the existing suboptimal APIs anyway even if others want to take advantage of newer, better APIs and idioms.</div></div></div></blockquote><div class=""><br class=""></div><div class="">I’m not sure what you mean.&nbsp; I’m talking about two things specifically:</div><div class=""><br class=""></div><div class="">1) APIs that are already deprecated and have replacements.&nbsp; The deprecated version goes in this library, avoid carrying them around forever.</div><div class=""><br class=""></div><div class="">2) APIs that are used by extremely narrow audiences, which were added without much consideration and that have not been redesigned since Swift 1.&nbsp; Mirror’s are an example of this.&nbsp; I’m arguing that these should be moved to this SwiftDeprecated module - but not actually deprecated until a replacement exists.</div><div class=""><br class=""></div><div class="">I don’t see how this is bad for anyone, and I think this provides a significant process improvement compared to your current approach, which forces you to lock down APIs now without careful consideration just because they are not “important enough”.</div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap:break-word;line-break:after-white-space" class=""><div class="">The main cost I see here that we save by having an “overlay for the Standard library" is code size. &nbsp;</div></div></div></blockquote><div class=""><br class=""></div><div class="">I don’t understand this point.</div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap:break-word;line-break:after-white-space" class=""><div class="">On macOS/iOS it is true that applications embed a copy of the Standard Library within them and thus pay a real cost in the Standard Library’s actually payload size in their own app.&nbsp; However, the only reason that is necessary today is because we don’t have ABI stability.&nbsp; With ABI stability, other options for shipping the Standard Library — such as shipping it in the OS — become possible, and thus the burden of shouldering that “cost” of code size shifts around.&nbsp; Then the tradeoffs of having an overlay for the Standard Library are different.&nbsp; In a world with ABI stability, is it better to have a Standard Library "overlay" that only some clients use, and embed within their application bundle, than just eat that cost in the Standard Library to be shared by potentially multiple clients installed on a system?&nbsp; I think it really comes down to the numbers.&nbsp; In that case, are we really just talking about Mirrors?&nbsp; I haven’t run the numbers here, but my intuition tells me we are talking about a relatively small code size impact overall.</div></div></div></blockquote><div class=""><br class=""></div><div class="">This comment doesn’t make a lot of sense to me, perhaps we’re talking across each other.&nbsp; The point of the design that I’m advocating for is that all apps (that deploy to iOS-next or later) get a immediate improvement from abi stability: the vast majority of the standard library is not put into their app bundle.&nbsp; Further, the vastly most common apps - those that are not using mirrors or deprecated APIs, also do not include the SwiftDeprecated module. &nbsp;</div><div class=""><br class=""></div><div class="">Only the tiny minority of apps that do use these APIs would have a copy of SwiftDeprecated in their app dylib, but they have a path to fix that, and they would still see a huge improvement from the bulk of the standard library being out of their app bundle.</div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap:break-word;line-break:after-white-space" class=""><div class=""><br class=""></div><div class="">There’s also other potential performance implications from doing this split. &nbsp;</div></div></div></blockquote><div class=""><br class=""></div><div class="">This doesn’t make sense to me.&nbsp; We’re not talking about taking comonly used apis here.&nbsp; Mirrors are not performance sensitive at all, and neither are deprecated wrappers of renamed APIs.</div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap:break-word;line-break:after-white-space" class=""><div class="">Being able to have the Standard Library be in the OS has potential major implications on the startup time of Swift applications.</div></div></div></blockquote><div class=""><br class=""></div><div class="">It is great for app developers to have an incentive to stop using deprecated APIs! :-)</div><br class=""><blockquote type="cite" class=""><div style="word-wrap:break-word;line-break:after-white-space" class=""><div class="">Can you elaborate a bit more on the specific “cost” factors you are using when proposing to have a Standard Library overlay?</div></div></blockquote><br class=""></div><div class="">I think it is possible that you’re reading too much into the “overlay" word here, so ignore that.&nbsp; The design I’m proposing is really simple:</div><div class=""><br class=""></div><div class="">1. The vast majority of the standard library goes into the OS.&nbsp; This includes all the string, array, and other stuff people use.</div><div class="">2. The deprecated wrappers and obscure APIs go into a new module, and that module doesn’t go into the OS.&nbsp; Only people that use it pay to cost.</div><div class=""><br class=""></div><div class="">This isn’t particularly complicated, if give you new ways to manage the process of stdlib ABI stability, and I don’t see the downside.</div><div class=""><br class=""></div><div class="">-Chris</div><div class=""><br class=""></div><div class=""><br class=""></div><br class=""></div></div></blockquote></div><br class=""></div></div>_______________________________________________<br class="">
swift-evolution mailing list<br class="">
<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a><br class="">
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="">
</blockquote></div>
</div></blockquote></div><br class=""></div></body></html>