> On Oct 6, 2017, at 11:06 PM, Chris Lattner via swift-dev 
> <swift-dev@swift.org> wrote:
> 
> This question is somewhere between swift-dev and swift-users, not sure where 
> best to post this.  
> 
> I’m working on a project that wants to get very low-abstraction penalty array 
> operations, particularly with varargs.

It’s awesome to hear you’re still using Swift ;-)

>  Given the currently language limitations (no fixed size arrays), the best 
> I’ve been able to come up with is something like this, where “lowlevelAPI” 
> contains the heavy lifting (and is assumed to be opaque), and the “safeAPI” 
> wrappers exist merely to provide a convenient safe wrapper for clients:
> 
> <array_abstraction.swift>
> 
> Given whole module optimization of the program, we should in principle, be 
> able to optimize this down to the equivalent of an LLVM array alloca in the 
> clients, a few stores to it, then passing the pointers to the LLVM alloca 
> into lowlevelAPI.  However, Swift is not doing this, not even with:
> 
> $ swiftc array_abstraction.swift -emit-sil -o - -O 
> 
> In this trivial case (with constant initializers) it does do the “array 
> outlining” optimization, but this is no where near the abstraction level it 
> could be.
> 
> Is there a better way to achieve this, and if not, is there any planned work 
> (perhaps aligned with the ABI stability efforts) to improve vararg array 
> performance to be able to avoid heap abstractions?  Any individual call to a 
> vararg array is a known length, so it is a perfect candidate for a stack 
> allocation.

In fact I filed an internal radar about this a while ago, but the discussion 
didn’t go anywhere because we had bigger fish to fry. I think the main 
difficulty is that we would need some kind of “copy-on-escape” sequence type. 
Iterating over the vararg inside the callee should be efficient, but if I then 
take the value and store it somewhere else, it would need to copy the buffer 
from the stack to the heap.

Also there were source stability implications because people assume the vararg 
argument inside the function body is literally a Swift.Array.

Perhaps the work being done on ownership can help here though. In the ownership 
manifesto, John describes a ‘shared’ attribute on function parameters. What if 
I declare my vararg as shared:

func takesArgs(_ xs: shared Int…)

This means the caller is passing along a borrowed value, not the value itself. 
With today’s vararg implementation this would just pass the Array<Int> at +0, 
but perhaps this can be the extension point where we introduce the 
stack-allocated varargs that you propose, and say that a ‘shared’ vararg 
argument actually has a more efficient representation. This allows it to be 
introduced additively without breaking ABI or source compatibility.

What do you think?

Slava


> 
> -Chris
> 
> 
> _______________________________________________
> swift-dev mailing list
> swift-dev@swift.org
> https://lists.swift.org/mailman/listinfo/swift-dev

_______________________________________________
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev

Reply via email to