Skip to content

nonmutating swapAt implementations for UnsafeMutable(Raw)BufferPointer #13071

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 15, 2018

Conversation

glessard
Copy link
Contributor

The BufferPointer types currently use MutableCollection's default implementation of swapAt, which is unnecessarily mutable and, in the case of UnsafeMutableBufferPointer does nothing to minimize ARC traffic. This PR introduces non-mutating implementations of swapAt for UnsafeMutableBufferPointer and UnsafeMutableRawBufferPointer, in the spirit of #12504. If this gets merged some new "un-mutated var" warnings may appear, but source code would otherwise be unaffected.

Copy link
Contributor

@atrick atrick left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@@ -492,6 +492,29 @@ public struct Unsafe${Mutable}RawBufferPointer
% end # mutable
}

%if Mutable:
/// Exchanges the byte values at the specified offsets
/// in the memory region
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we have a period (.) at the end of this sentence.

/// Exchanges the byte values at the specified offsets
/// in the memory region
///
/// Both parameters must be valid indices, and not
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...valid indices in the memory region?

let pi = (_position! + i)
let pj = (_position! + j)
let tmp = pi.load(fromByteOffset: 0, as: UInt8.self)
pi.copyBytes(from: pj, count: MemoryLayout<UInt8>.size)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not count: 1? If UInt8 is not one byte, then you've broken the semantic guarantees of the method anyway.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not count: 1?

True. Using literal 1 would me more consistent with the pointer arithmetic above.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think using an explicitly typed value from MemoryLayout is more consistent with the load and storeBytes methods, which must be typed.

@@ -492,6 +492,29 @@ public struct Unsafe${Mutable}RawBufferPointer
% end # mutable
}

%if Mutable:
/// Exchanges the byte values at the specified offsets
/// in the memory region.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: What is the difference in meaning between this “in the memory region” and the documentation for the other method which says, “of the buffer”?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"memory region" is used regularly in the UnsafeRawPointer documentation, which I interpret as emphasis on the untyped nature of raw pointers; I didn't use it well here.

@glessard glessard force-pushed the umbp-nonmutating-swapat branch from b1aae41 to 72f1dac Compare November 27, 2017 01:57
@airspeedswift
Copy link
Member

@swift-ci please test

@glessard glessard force-pushed the umbp-nonmutating-swapat branch 4 times, most recently from b2c2769 to a0722b2 Compare December 7, 2017 05:03
@glessard
Copy link
Contributor Author

@atrick I realized that one thing these implementations lose is any debug-mode bounds checking. (The default implementation gets it for free by using the subscript). Would it be better to add some _debugPrecondition calls or leave it alone?

@atrick
Copy link
Contributor

atrick commented Dec 16, 2017

Thanks.

@glessard glessard force-pushed the umbp-nonmutating-swapat branch 2 times, most recently from 13b3ab4 to 829977f Compare December 22, 2017 18:04
@glessard glessard force-pushed the umbp-nonmutating-swapat branch from 829977f to 0c95f90 Compare March 6, 2018 16:15
@glessard
Copy link
Contributor Author

@atrick Sorry to bother again, but this seems to have fallen off everyone's radar…

@atrick
Copy link
Contributor

atrick commented Mar 15, 2018

@swift-ci test.

@atrick atrick merged commit afbcbfd into swiftlang:master Mar 15, 2018
@glessard
Copy link
Contributor Author

Thanks!

@atrick
Copy link
Contributor

atrick commented Mar 16, 2018

@glessard thanks for bring this to my attention again. It should have been merged a long time ago!

@glessard
Copy link
Contributor Author

I thought for a moment it was waiting for 4.1, but then it didn't look like it!
Is the comment at https://github.com/apple/swift/blob/b506cbadb230b670f741eb798983197358b10dea/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb#L152 still relevant? That would be a quick one...

@atrick
Copy link
Contributor

atrick commented Mar 16, 2018

@glessard We need a motivating benchmark for a change like that. If a motivating benchmark exists then it's certainly relevant.

@glessard
Copy link
Contributor Author

@atrick Is it sufficient to start a PR and benchmark it from there? I imagine that if the change is not positive then it would equally justify removing the specialized forms from UnsafeMutableBufferPointer<T>. Seems to me that it would make sense to clear this up before the ABI is frozen.

@atrick
Copy link
Contributor

atrick commented Mar 16, 2018

Hopefully there's already a benchmark that relies on the non-raw pointer specialization. I mean that a PR for raw pointer specialization needs to include such a benchmark. I suspect that we don't already have one. The benchmarks only cover things that have already been deliberately optimized.

@glessard
Copy link
Contributor Author

Now I see what you meant. I'll see what I can do, then.

@glessard glessard deleted the umbp-nonmutating-swapat branch March 18, 2018 14:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants