As of Swift 4.1, the "these are for internal stdlib use only: use at your own risk" annotations @_inlineable and @_versioned have the same semantics as @inlineable and @usableFromInline respectively.
It's still not ideal, but nothing is.
As of Swift 4.1, the "these are for internal stdlib use only: use at your own risk" annotations @_inlineable and @_versioned have the same semantics as @inlineable and @usableFromInline respectively.
It's still not ideal, but nothing is.
I tried to make this all clear in my earlier post:
When I said "explicitly defining all implicit methods" I was mainly referring to default constructors. I'm not sure what @Nobody1707 thinks I'm mistaken about.
You can distribute your library as source and users can drop it into their project. If it needs to be distributed as a separate module then you'll have to rewrite your APIs and likely use some underscored attributes as if it were a resilient library. The compiler simply doesn't support optimizing across non-resilient libraries.
@Andrew_Trick - thank you for the clarification.
Then IMO (as a new user) it's a bit disingenuous for the project to claim that this language supports generics, at least in any usable capacity. That is, one of the prime uses for generics is to provide the ability to write flexible libraries that other packages can use on their own types without having a huge performance hit. My conclusion is that there's very little benefit to writing a generic graph library parameterized on various integers (which is what I was trying to do) when I can't write any performant code to go with it. To be specific, I implemented Dijkstra's Shortest Paths algorithm for my AbstractGraph type. When all of my code was in a single package, I was able to get speeds on par with C++ (5 seconds on a 30 million edge graph). When I moved the AbstractGraph extension and related code into a separate library and just imported it to a simple executable, the exact same function took 50 seconds.
I've been playing around with @_specialize a bit but I've run into a bit of a problem with it inside an extension, so I don't think it's going to work. Unless I can figure out a way to get generics working in a performant manner, I'm going to have to put Swift on hold for a bit as it won't be usable for my current projects.
(I should add that I would be extremely grateful to anyone who could prove my assertion wrong, as I really like this language otherwise.)
I'm sorry, I misunderstood you as saying that there was currently no way for a third party to write a resilient library.
![]()
![]()
![]()
I hope we can reach a clear explanation and thorough understanding of this by the end of this thread… as I am now thoroughly confused by this.
@Andrew_Trick are you saying that if developers were to write reusable pieces of code and structure the basic buildings blocks as modules for sharing and easy inclusion via SwiftPM, that SE-0193 Cross-module inlining and specialization isn’t intended as a way to enable the mother of all optimizations — inlining — of such generic code, further enabling optimizations like specialization etc., without which the Swift’s whole story about Protocol-Oriented Programming and Embracing Algorithms is all but a pipe dream due to orders of magnitude slower performance?
Are we talking about “modules” as in code organization unit or binary distribution package?
At the moment you have to copy the source code into an Xcode project (assuming Xcode). Cocoa Pods etc can make this easier.
The issue is that everything except Apple libraries are statically linked. At some point, hopefully, there will be a module system and a thriving 3rd party library scene. Whilst not as good as other languages just at the moment, Cocoa Pods etc are useable.
Once you have source code the optimisation is fine
It’s not that bad.
Howard, that’s total non-sequitur. If we pretend the problem doesn’t exists, it isn’t a problem?!?
Well, yes, I suppose that's what I'm saying. My intent was only to correct some misstatements earlier in this thread though, not shock anyone. I'll restate the key points:
@usableFromInline does not expose the body of a function/method for inlining. You'll need to use @inlinable to get that which means artificially changing the visibility of some declarations.
The SE-0193 features aren't primarily designed for cross-module optimization of swiftpm packages. If they were, they would look and act differently. e.g. @inlinable wouldn't have strange restrictions, and @usableForInline wouldn't exist at all. They are absolutely essential for shipping a high performance resilient library (with binary stability), like the standard library, so it's great news that we have them.
I think it does make sense to commandeer @inlinable and friends to ship a generic library as a swiftpm package (I think @sbromberger is reporting some success now) Please realize that you're doing this to work around a build system/compiler deficiency. It's not part of anyone's master plan to force developers who are distributing libraries in source form to sprinkle highly confusing annotations.
I do not think it makes sense to split an Xcode project into modules under the assumption that the cross module optimization problem is solved. Feel free to split up the project along boundaries that are not performance sensitive. If you run into performance problems, @inlinable and friends can help. But, again, that's not primarily what they were designed for.
I think the problem is that we don't make a clear distinction. I've been refering the "modules as code organization" as non-resilient modules and "modules as a stable binary" as resilient.
I've run into limitations with @_specialize because there's no way to invoke a default method from within an override. Have you filed a bug against your issue? Someone may be able to suggest a workaround.
That requires also a change in the way CocoaPods let us deal with them as, if I am not mistaken, each imported Library is a separate module. So it is a problem with pods at the moment too (say for framework makers that also created their own applications from the same pods they send out to their trusted partners too), correct?
Regarding pods, most pods are dynamic framework nonetheless (1.5.3 is starting to make it easier to move to static ones though).
You are correct, I should have said CocoaPods 1.5 onwards and static linking only. You need to use static linking to get the optimizations to work.
Andrew, thank you for clearing that up for me.
Is it fair to say that Swift is lacking cross module specialization? Or cross module optimizations in general? How does a future roadmap look from that perspective?
Without commenting on the rest of the thread, I want to note that this is incorrect. @inlinable works just fine on internal functions—it was an important part of the review feedback for the proposal. (Can someone file a bug about the error message being wrong?)
Internally, the compiler has the basic ability to specialize and optimize across modules into which it is granted visibility. The developer model for doing this across resilient libraries is laid out in SE-0193 (@inlinable and such). Those features will evolve and become more convenient and powerful. The developer model for doing this across non-resilient libraries doesn't exist yet. So, if you're distributing, for example, a generic graph library, either (1) your users will need to rig their build system to merge modules, (2) they will take a substantial unnecessary performance penalty, or (3) you will annotate your code with attributes that are unnecessarily awkward and limited for your purpose. That's better then the previous situation, in which option (3) didn't exist. It just seems to have confused a number people as to the long-term intent of those new attributes.
Is there something tracking this, either an SR or an evolution thread? I'm guessing this is going to be tackled when the module format/etc is nailed down. Because this is a huge issue which is actively causing potential Swift adopters to look elsewhere.
I didn't see a bug on this yet. I filed this
Incorrect error message: '@inlinable' attribute can only be applied to public declarations
Sorry, I should have clarified that earlier in this thread. When I refer to "adjusting visibility" in order to use @inlinable that means removing the private or fileprivate qualifiers from the declaration to make them internal.
I agree that this needs to be discussed elsewhere. There have been threads on "submodules" but I don't think that completely covers the use cases. To be clear, I'm talking distributing pure source libraries, so the module format would be irrelevant.
So what is the verdict on how Swift libraries should be distributed? it sounds a lot like “none of the above, wait until Swift 7” atm
Well, that's a good question but I can't state a verdict. I suggest starting a different thread and clearly framing the question in terms of the use case. I think this is really a question about distributing packages via swiftpm?
I mean, you can distribute your libraries as source today, and they may have inadequate performance, in which case you may have to manually deal with inlinability annotations to recover some of that performance. In the fullness of time, we'll fix the compiler, and your library will get faster "for free".
As a different stopgap, you can present your library as a file or files to be added directly into users' modules.