-
Notifications
You must be signed in to change notification settings - Fork 10.4k
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
Data Inlinability Refinements #21754
Data Inlinability Refinements #21754
Conversation
@swift-ci Please smoke test |
@swift-ci Please benchmark |
@@ -300,72 +296,24 @@ internal final class _DataStorage { | |||
_DataStorage.move(_bytes!.advanced(by: origLength), bytes, length) | |||
} | |||
|
|||
// fast-path for appending directly from another data storage | |||
@inlinable | |||
func append(_ otherData: _DataStorage, startingAt start: Int, endingAt end: Int) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These were simply never used.
@@ -17,7 +17,7 @@ import Darwin | |||
#elseif os(Linux) | |||
import Glibc | |||
|
|||
@inlinable | |||
@inlinable // This is @inlinable as trivially computable. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I audited every usage of @inlinable
and @usableFromInline
and gave each one a justification for keeping it or changing it. I tried to be consistent with explanations.
@@ -62,14 +62,14 @@ internal func __NSDataIsCompact(_ data: NSData) -> Bool { | |||
|
|||
#endif | |||
|
|||
// Underlying storage representation for medium and large data. | |||
// Inlinability strategy: methods from here should not inline into InlineSlice or LargeSlice unless trivial. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Every type I audited now has a description of what inlinability we're aiming for.
func copyBytes(to pointer: UnsafeMutableRawPointer, from range: Range<Int>) { | ||
let offsetPointer = UnsafeRawBufferPointer(start: _bytes?.advanced(by: range.lowerBound - _offset), count: Swift.min(range.upperBound - range.lowerBound, _length)) | ||
UnsafeMutableRawBufferPointer(start: pointer, count: range.upperBound - range.lowerBound).copyMemory(from: offsetPointer) | ||
} | ||
|
||
@inlinable | ||
func replaceBytes(in range: NSRange, with bytes: UnsafeRawPointer?) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also never used
This looks good to me. I think the commentary on the functions really helps clear up why the inlines should be the way they are. +1 for maintainability. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pending the results of course.
Build comment file:Performance: -O
Code size: -O
Performance: -Osize
Code size: -Osize
Performance: -Onone
Code size: -swiftlibs
How to read the dataThe tables contain differences in performance which are larger than 8% and differences in code size which are larger than 1%.If you see any unexpected regressions, you should consider fixing the Noise: Sometimes the performance results (not code size!) contain false Hardware Overview
|
Looks like the failing test is one that asserts that |
I think we don't have any benchmarks that cover the @itaiferber Could we add additional benchmark(s?) that cover that (and the |
Sure, I can put those up separately. I don't expect any significant regressions in hashing performance. |
@swift-ci Please smoke test |
@palimondo As for the 20x speedup — unfortunately, looks the initial numbers I get for the benchmark are also way, way slower than what we're getting here in CI (2 orders of magnitude off), and the improved numbers are significantly slower than what we're seeing in CI as well. Looks like this is just on my machine; unfortunately, less impressive in practice. |
@airspeedswift Regarding lack of use of |
// If we've still got bytes left in the buffer (i.e. the loop ended before we filled up the buffer and cleared it out), append them. | ||
if buffer.count > 0 { | ||
buffer.withUnsafeBytes { _representation.append(contentsOf: $0) } | ||
buffer.count = 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You'll be throwing away (releasing) the buffer
as you exit this block, so resetting the count
is unnecessary.
// If we've still got bytes left in the buffer (i.e. the loop ended before we filled up the buffer and cleared it out), append them. | ||
if buffer.count > 0 { | ||
buffer.withUnsafeBytes { _representation.append(contentsOf: $0) } | ||
buffer.count = 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't need to reset this on exit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I realize — I was hoping to avoid future bugs in case someone tries to use buffer
after this last write. I'll leave a comment instead.
test/stdlib/TestData.swift
Outdated
var d = Data() | ||
|
||
// d should go from .empty representation to .inline. | ||
// Appending a small enough sequence to fit in linline should actually be copied. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: linline
…nchmarks Additional Data benchmarks (cherry picked from commit 1d10a6a)
@swift-ci Please smoke test |
@swift-ci Please benchmark |
Build comment file:Performance: -O
Code size: -O
Performance: -Osize
Code size: -Osize
Performance: -Onone
Code size: -swiftlibs
How to read the dataThe tables contain differences in performance which are larger than 8% and differences in code size which are larger than 1%.If you see any unexpected regressions, you should consider fixing the Noise: Sometimes the performance results (not code size!) contain false Hardware Overview
|
@swift-ci Please smoke test and merge |
@swift-ci Please smoke test |
Is this still considered WIP? Will you be cherry-picking this for 5.0 branch? |
@palimondo I'm cherry-picking for swift-5.0-branch right now |
…refinements Refine Data inlinability (cherry picked from commit 6c57610)
@itaiferber Didn't you forget to push some last commit? The code that landed here still contains unresolved issues around |
No, we don't intend to change that behavior in this PR — if we'd like to make the changes, we can do that separately in a different PR. Given that the |
What's in this pull request?
Pulls back some of the aggressive inlining we did in #20225 to hopefully improve some code size measurements. Local benchmarks look good speed-wise, but I'll be using CI to measure code size improvements.
Also resolves 46780357 regarding
Data.hashValue
inlining (which has been replaced withData.hash(into:)
).Commit-by-commit review is recommended, and I took the liberty of bringing some of the changes I'd made in swift-5.0-branch back into master (e.g. eliminating
numericCast
in favor of explicitInt
conversions as requested by @airspeedswift)