> On Sep 6, 2017, at 1:12 PM, Joe Groff via swift-evolution 
> <swift-evolution@swift.org> wrote:
> 
>> 
>> On Sep 6, 2017, at 1:06 PM, Taylor Swift <kelvin1...@gmail.com> wrote:
>> 
>> 
>> 
>> On Wed, Sep 6, 2017 at 12:41 PM, Joe Groff via swift-evolution 
>> <swift-evolution@swift.org> wrote:
>>> Currently, memory is deallocated by an instance method on 
>>> UnsafeMutablePointer, deallocate(count:). Like much of the Swift pointer 
>>> API, performing this operation on a buffer pointer requires extracting 
>>> baseAddress! and count. It is very common for the allocation code above to 
>>> be immediately followed by:
>>> 
>>> defer
>>> 
>>> {
>>>    buffer.
>>> baseAddress?.deallocate(capacity: buffer.count
>>> )
>>> }
>>> 
>>> This method is extremely problematic because nearly all users, on first 
>>> seeing the signature of deallocate(capacity:), will naturally conclude from 
>>> the capacity label that deallocate(capacity:) is equivalent to some kind of 
>>> realloc()that can only shrink the buffer. However this is not the actual 
>>> behavior — deallocate(capacity:) actually ignores the capacity argument and 
>>> just calls free() on self. The current API is not only awkward and 
>>> suboptimal, it is misleading. You can write perfectly legal Swift code that 
>>> shouldn’t segfault, but still can, for example
>>> 
>>> var ptr = UnsafeMutablePointer<UInt8>.allocate(capacity: 1000000
>>> )
>>> ptr.
>>> initialize(to: 13, count: 1000000
>>> )
>>> ptr.
>>> deallocate(capacity: 500000) // deallocate the second half of the memory 
>>> block
>>> ptr[0] // segmentation fault
>>> where the first 500000 addresses should still be valid if the documentation 
>>> is to be read literally.
>> 
>> The fact that the Swift runtime currently uses malloc/free is an 
>> implementation detail. Tracking deallocation size is a very useful 
>> optimization for better allocator backends, and C++ underwent an ABI break 
>> to make it so that sized delete can be supported. Maybe we can change the 
>> name to `deallocate(allocatedCapacity:)` to make it clear that it isn't 
>> resizing the memory, and/or make the capacity argument optional so that you 
>> can pay for the overhead of the allocator deriving the size if it's 
>> inconvenient for the calling code to carry the size around, but we shouldn't 
>> remove the functionality altogether.
>> 
>> -Joe
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> 
>> The idea is to get the house in order by removing all parameters from 
>> deallocate(), since that’s what it really does right now. Then, in the 
>> future, if Swift gets a more sophisticated allocator backend, a new method 
>> like deallocate(capacity:) or reallocate(toCapacity:) could be added without 
>> conflicting with the currently named deallocate(capacity:). However, using 
>> the function signature to pretend that it does something it can’t actually 
>> do right now is extremely dangerous.
> 
> I don't think that's a good idea in this case, because it's not unlikely we 
> would explore an optimized allocator soon after ABI stability, and 
> retrofitting these interfaces in a future version of Swift would put a 
> deployment target limit on when they can be used, and mean that a lot of user 
> code would need to be retrofitted to carry allocated capacities where needed 
> to see any benefit.
> 
> -Joe


The fact that we’re using malloc and free is already part of the ABI because 
old libraries need to be able to deallocate memory allocated by newer libraries.

Within the standard library we could make use of some new deallocation fast 
path in the future without worrying about backward deployment.

Outside of the standard library, clients will get the benefits of whatever 
allocator is available on their deployed platform because we now encourage them 
to use UnsafeBufferPointer.deallocate(). We can change the implementation 
inside UnsafeBufferPointer all we want, as long as it’s still malloc-compatible.

I’m sure we’ll want to provide a better allocation/deallocation API in the 
future for systems programmers based on move-only types. That will already be 
deployment-limited.

Absolute worst case, we introduce a sized UnsafePointer.deallocate in the 
future. Any new code outside the stdlib that wants the performance advantage 
would either need to
- trivially wrap deallocation using UnsafeBufferPointer
- create a trivial UnsafePointer.deallocate thunk under an availability flag

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

Reply via email to