[swift-dev] @owned vs @guaranteed convention for 'self' in nonmutating value type methods

Joe Groff jgroff at apple.com
Tue Jan 19 09:42:20 CST 2016


> On Jan 18, 2016, at 8:47 PM, Michael Gottesman <mgottesman at apple.com> wrote:
> 
> 
>> On Jan 18, 2016, at 11:28 AM, Joe Groff via swift-dev <swift-dev at swift.org> wrote:
>> 
>> For Swift 2, we changed the default reference counting convention for 'self' parameters from +1 "owned" (caller retains, callee releases) to +0 "guaranteed" (caller retains and releases). This makes a lot of sense for class methods, since it's common to invoke a number of methods on the same object in turn. Similarly for value types, it's common to want to perform a bunch of mutations in a row, but we get a "+0"-like convention naturally due to the way 'inout' works. For nonmutating value type operations, it's a bit less clear-cut—a pure operation is more likely to appear once as part of a larger expression.
> 
> I guess you are implying here that we would be forwarding along self in the complicated computation? Wouldn't we at most have one retain/release for the expression on the value due to SILGen peepholes/SGFContexts (maybe my memory is wrong)?

Yeah.

> 
>> Using +0 also prevents us from reusing self's resources
> 
> Can you elaborate?
> 
>> and doing in-place mutation if it's uniquely referenced
> 
> I thought we were talking about non-mutating value type methods? (I am confused). Can you elaborate here?

A nonmutating operation on an Array can mutate its 'self' parameter's buffer to build its return value if the parameter is uniquely referenced, for instance:

extension Array {
  func appending(x: Array) -> Array {
    var myself = self // should take self's refcount
    if isUniquelyReferenced(&myself.buffer) {
      myself.append(x)
      return myself
    }
    ...
  }
}

The effect is still semantically nonmutating, but we get the benefits of in-place mutation.

> 
>> , which is an extremely useful optimization for a number of operations on strings and containers. We may want to consider whether +1 is a better default, if not for all nonmutating value type methods, maybe some subset where inplace mutation is likely to be profitable. One possible heuristic would be to look at whether a method returns the Self type (possibly including tuples and fragile structs containing Self, or different instantiations of the same Self type).
> 
> We need to be very careful here. We saw large reductions in the number of dynamic retains/releases at -Onone and significant improvements at -O across many benchmarks.

I know we've done all-or-nothing tests for +0 vs +1. I think it'd be worthwhile to experiment with selectively using +1 for value type methods and seeing what the impact is. My hypothesis is that most value type 'self's are effectively forwarded and can be more efficiently callee-consumed than caller-guaranteed.

-Joe

> 
>> 
>> -Joe
>> _______________________________________________
>> swift-dev mailing list
>> swift-dev at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-dev
> 



More information about the swift-dev mailing list