diff --git a/Sources/NIO/ByteBuffer-aux.swift b/Sources/NIO/ByteBuffer-aux.swift index 568ad433aee..cea17fdedc3 100644 --- a/Sources/NIO/ByteBuffer-aux.swift +++ b/Sources/NIO/ByteBuffer-aux.swift @@ -34,7 +34,7 @@ extension ByteBuffer { // this is not technically correct because we shouldn't just bind // the memory to `UInt8` but it's not a real issue either and we // need to work around https://bugs.swift.org/browse/SR-9604 - Array(UnsafeRawBufferPointer(rebasing: ptr[range]).bindMemory(to: UInt8.self)) + Array(UnsafeRawBufferPointer(fastRebase: ptr[range]).bindMemory(to: UInt8.self)) } } @@ -139,7 +139,7 @@ extension ByteBuffer { } return self.withUnsafeReadableBytes { pointer in assert(range.lowerBound >= 0 && (range.upperBound - range.lowerBound) <= pointer.count) - return String(decoding: UnsafeRawBufferPointer(rebasing: pointer[range]), as: Unicode.UTF8.self) + return String(decoding: UnsafeRawBufferPointer(fastRebase: pointer[range]), as: Unicode.UTF8.self) } } @@ -210,7 +210,7 @@ extension ByteBuffer { self.withVeryUnsafeMutableBytes { destCompleteStorage in assert(destCompleteStorage.count >= index + allBytesCount) let dest = destCompleteStorage[index ..< index + allBytesCount] - dispatchData.copyBytes(to: .init(rebasing: dest), count: dest.count) + dispatchData.copyBytes(to: .init(fastRebase: dest), count: dest.count) } return allBytesCount } @@ -228,7 +228,7 @@ extension ByteBuffer { return nil } return self.withUnsafeReadableBytes { pointer in - return DispatchData(bytes: UnsafeRawBufferPointer(rebasing: pointer[range])) + return DispatchData(bytes: UnsafeRawBufferPointer(fastRebase: pointer[range])) } } @@ -396,7 +396,7 @@ extension ByteBuffer { precondition(count >= 0, "Can't write fewer than 0 bytes") self.reserveCapacity(index + count) self.withVeryUnsafeMutableBytes { pointer in - let dest = UnsafeMutableRawBufferPointer(rebasing: pointer[index ..< index+count]) + let dest = UnsafeMutableRawBufferPointer(fastRebase: pointer[index ..< index+count]) _ = dest.initializeMemory(as: UInt8.self, repeating: byte) } return count diff --git a/Sources/NIO/ByteBuffer-core.swift b/Sources/NIO/ByteBuffer-core.swift index 88b72a12493..2bea9ad61fb 100644 --- a/Sources/NIO/ByteBuffer-core.swift +++ b/Sources/NIO/ByteBuffer-core.swift @@ -379,7 +379,7 @@ public struct ByteBuffer { @inlinable mutating func _setBytesAssumingUniqueBufferAccess(_ bytes: UnsafeRawBufferPointer, at index: _Index) { - let targetPtr = UnsafeMutableRawBufferPointer(rebasing: self._slicedStorageBuffer.dropFirst(Int(index))) + let targetPtr = UnsafeMutableRawBufferPointer(fastRebase: self._slicedStorageBuffer.dropFirst(Int(index))) targetPtr.copyMemory(from: bytes) } @@ -389,7 +389,7 @@ public struct ByteBuffer { mutating func _setSlowPath(bytes: Bytes, at index: _Index) -> _Capacity where Bytes.Element == UInt8 { func ensureCapacityAndReturnStorageBase(capacity: Int) -> UnsafeMutablePointer { self._ensureAvailableCapacity(_Capacity(capacity), at: index) - let newBytesPtr = UnsafeMutableRawBufferPointer(rebasing: self._slicedStorageBuffer[Int(index) ..< Int(index) + Int(capacity)]) + let newBytesPtr = UnsafeMutableRawBufferPointer(fastRebase: self._slicedStorageBuffer[Int(index) ..< Int(index) + Int(capacity)]) return newBytesPtr.bindMemory(to: UInt8.self).baseAddress! } let underestimatedByteCount = bytes.underestimatedCount @@ -513,7 +513,7 @@ public struct ByteBuffer { public mutating func withUnsafeMutableReadableBytes(_ body: (UnsafeMutableRawBufferPointer) throws -> T) rethrows -> T { self._copyStorageAndRebaseIfNeeded() let readerIndex = self.readerIndex - return try body(.init(rebasing: self._slicedStorageBuffer[readerIndex ..< readerIndex + self.readableBytes])) + return try body(.init(fastRebase: self._slicedStorageBuffer[readerIndex ..< readerIndex + self.readableBytes])) } /// Yields the bytes currently writable (`bytesWritable` = `capacity` - `writerIndex`). Before reading those bytes you must first @@ -529,7 +529,7 @@ public struct ByteBuffer { @inlinable public mutating func withUnsafeMutableWritableBytes(_ body: (UnsafeMutableRawBufferPointer) throws -> T) rethrows -> T { self._copyStorageAndRebaseIfNeeded() - return try body(.init(rebasing: self._slicedStorageBuffer.dropFirst(self.writerIndex))) + return try body(.init(fastRebase: self._slicedStorageBuffer.dropFirst(self.writerIndex))) } /// This vends a pointer of the `ByteBuffer` at the `writerIndex` after ensuring that the buffer has at least `minimumWritableBytes` of writable bytes available. @@ -587,7 +587,7 @@ public struct ByteBuffer { @inlinable public func withUnsafeReadableBytes(_ body: (UnsafeRawBufferPointer) throws -> T) rethrows -> T { let readerIndex = self.readerIndex - return try body(.init(rebasing: self._slicedStorageBuffer[readerIndex ..< readerIndex + self.readableBytes])) + return try body(.init(fastRebase: self._slicedStorageBuffer[readerIndex ..< readerIndex + self.readableBytes])) } /// Yields a buffer pointer containing this `ByteBuffer`'s readable bytes. You may hold a pointer to those bytes @@ -605,7 +605,7 @@ public struct ByteBuffer { public func withUnsafeReadableBytesWithStorageManagement(_ body: (UnsafeRawBufferPointer, Unmanaged) throws -> T) rethrows -> T { let storageReference: Unmanaged = Unmanaged.passUnretained(self._storage) let readerIndex = self.readerIndex - return try body(.init(rebasing: self._slicedStorageBuffer[readerIndex ..< readerIndex + self.readableBytes]), + return try body(.init(fastRebase: self._slicedStorageBuffer[readerIndex ..< readerIndex + self.readableBytes]), storageReference) } diff --git a/Sources/NIO/ByteBuffer-int.swift b/Sources/NIO/ByteBuffer-int.swift index abd15b7ec68..f0cf5ab20d5 100644 --- a/Sources/NIO/ByteBuffer-int.swift +++ b/Sources/NIO/ByteBuffer-int.swift @@ -62,7 +62,7 @@ extension ByteBuffer { return self.withUnsafeReadableBytes { ptr in var value: T = 0 withUnsafeMutableBytes(of: &value) { valuePtr in - valuePtr.copyMemory(from: UnsafeRawBufferPointer(rebasing: ptr[range])) + valuePtr.copyMemory(from: UnsafeRawBufferPointer(fastRebase: ptr[range])) } return _toEndianness(value: value, endianness: endianness) } diff --git a/Sources/NIO/ControlMessage.swift b/Sources/NIO/ControlMessage.swift index efefb102d65..294662bad73 100644 --- a/Sources/NIO/ControlMessage.swift +++ b/Sources/NIO/ControlMessage.swift @@ -52,7 +52,7 @@ struct UnsafeControlMessageStorage: Collection { /// Get the part of the buffer for use with a message. public subscript(position: Int) -> UnsafeMutableRawBufferPointer { return UnsafeMutableRawBufferPointer( - rebasing: self.buffer[(position * self.bytesPerMessage)..<((position+1) * self.bytesPerMessage)]) + fastRebase: self.buffer[(position * self.bytesPerMessage)..<((position+1) * self.bytesPerMessage)]) } var startIndex: Int { return 0 } @@ -239,7 +239,7 @@ struct UnsafeOutboundControlBytes { private mutating func appendGenericControlMessage(level: CInt, type: CInt, payload: PayloadType) { - let writableBuffer = UnsafeMutableRawBufferPointer(rebasing: self.controlBytes[writePosition...]) + let writableBuffer = UnsafeMutableRawBufferPointer(fastRebase: self.controlBytes[writePosition...]) let requiredSize = NIOBSDSocketControlMessage.space(payloadSize: MemoryLayout.stride(ofValue: payload)) precondition(writableBuffer.count >= requiredSize, "Insufficient size for cmsghdr and data") @@ -263,7 +263,7 @@ struct UnsafeOutboundControlBytes { if writePosition == 0 { return UnsafeMutableRawBufferPointer(start: nil, count: 0) } - return UnsafeMutableRawBufferPointer(rebasing: self.controlBytes[0 ..< self.writePosition]) + return UnsafeMutableRawBufferPointer(fastRebase: self.controlBytes[0 ..< self.writePosition]) } } diff --git a/Sources/NIO/PointerHelpers.swift b/Sources/NIO/PointerHelpers.swift new file mode 100644 index 00000000000..918fbf6dda3 --- /dev/null +++ b/Sources/NIO/PointerHelpers.swift @@ -0,0 +1,41 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the SwiftNIO open source project +// +// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors +// Licensed under Apache License v2.0 +// +// See LICENSE.txt for license information +// See CONTRIBUTORS.txt for the list of SwiftNIO project authors +// +// SPDX-License-Identifier: Apache-2.0 +// +//===----------------------------------------------------------------------===// + +// MARK: Rebasing shims + +// These methods are shimmed in to NIO until https://github.com/apple/swift/pull/34879 is resolved. +// They address the fact that the current rebasing initializers are surprisingly expensive and do excessive +// checked arithmetic. This expense forces them to often be outlined, reducing the ability to optimise out +// further preconditions and branches. +extension UnsafeRawBufferPointer { + @inlinable + init(fastRebase slice: Slice) { + let base = slice.base.baseAddress?.advanced(by: slice.startIndex) + self.init(start: base, count: slice.endIndex &- slice.startIndex) + } + + @inlinable + init(fastRebase slice: Slice) { + let base = slice.base.baseAddress?.advanced(by: slice.startIndex) + self.init(start: base, count: slice.endIndex &- slice.startIndex) + } +} + +extension UnsafeMutableRawBufferPointer { + @inlinable + init(fastRebase slice: Slice) { + let base = slice.base.baseAddress?.advanced(by: slice.startIndex) + self.init(start: base, count: slice.endIndex &- slice.startIndex) + } +}