Skip to content
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

Issue-2734 - Clamp buffer to maximum upon large write operation #2745

Merged
merged 18 commits into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
dcb0883
Issue-2734 - Clamp buffer to maximum upon large write operation
ali-ahsan-ali Jun 19, 2024
f5e43d0
Issue-2734 - Rename variable name on incorrect assumption
ali-ahsan-ali Jun 19, 2024
e02f3ef
Issue-2734 - Add extra checks to buffer clamp and edit api initialiser
ali-ahsan-ali Jun 24, 2024
01e8cf3
Issue-2734 - Clamp on readable bytes
ali-ahsan-ali Jun 26, 2024
825a6b3
Issue-2743 - Clamp after Flush
ali-ahsan-ali Jul 4, 2024
03f80cf
Issue-2743 - Add documentation for parameter
ali-ahsan-ali Jul 10, 2024
45f6b06
Issue-2734 - Address Feedback and reallocSlice
ali-ahsan-ali Jul 20, 2024
a48b322
Issues-2734 - Fix comment on shrink buffer function
ali-ahsan-ali Jul 27, 2024
8a05b6a
Merge branch 'main' into Issue-2734-shrink-buffer-after-write
weissi Aug 5, 2024
3da1d3a
Issue-2734 - Create static function for padding
ali-ahsan-ali Aug 6, 2024
56e2552
Merge branch 'main' into Issue-2734-shrink-buffer-after-write
ali-ahsan-ali Aug 6, 2024
99c2274
Merge branch 'main' into Issue-2734-shrink-buffer-after-write
Lukasa Aug 9, 2024
cb952f9
Issue-2734 - Address comment about unwritten bytes
ali-ahsan-ali Aug 10, 2024
4c8d94a
Issue-2734 - Address comment about rounding function
ali-ahsan-ali Sep 13, 2024
d5a2751
Merge branch 'main' into Issue-2734-shrink-buffer-after-write
weissi Sep 13, 2024
d9c6e8a
Merge branch 'main' into Issue-2734-shrink-buffer-after-write
weissi Sep 16, 2024
a8b8aec
Merge branch 'main' into Issue-2734-shrink-buffer-after-write
FranzBusch Sep 16, 2024
23ad4a0
Issue-2734 - Update doc
Sep 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions Sources/NIOCore/ByteBuffer-core.swift
Original file line number Diff line number Diff line change
Expand Up @@ -825,6 +825,23 @@ public struct ByteBuffer {
}
return true
}

/// Shrinks the buffers capacity to a `desiredCapacity` without altering readably bytes.
ali-ahsan-ali marked this conversation as resolved.
Show resolved Hide resolved
///
/// - Parameter desiredCapacity: The desired capacity for the buffers capacity to be shrunken to
/// - Returns: Bool indicating whether the buffer capacity has been shrunk to the desiredCapacity.
@inlinable
@discardableResult public mutating func shrinkBufferCapacity(to desiredCapacity: Int) -> Bool {
guard desiredCapacity < capacity, desiredCapacity > readableBytes else {
ali-ahsan-ali marked this conversation as resolved.
Show resolved Hide resolved
ali-ahsan-ali marked this conversation as resolved.
Show resolved Hide resolved
return false
}

let shrunkenCapacity = _toCapacity(desiredCapacity)
self._storage = self._storage.reallocSlice(self._slice.lowerBound..<self._slice.lowerBound + shrunkenCapacity, capacity: shrunkenCapacity)
ali-ahsan-ali marked this conversation as resolved.
Show resolved Hide resolved
self._slice = self._storage.fullSlice

return true
}

/// The reader index or the number of bytes previously read from this `ByteBuffer`. `readerIndex` is `0` for a
/// newly allocated `ByteBuffer`.
Expand Down
14 changes: 14 additions & 0 deletions Sources/NIOCore/Codec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -768,9 +768,16 @@ public final class MessageToByteHandler<Encoder: MessageToByteEncoder>: ChannelO
private var state: State = .notInChannelYet
private let encoder: Encoder
private var buffer: ByteBuffer? = nil
private let desiredBufferCapacity: Int?

public init(_ encoder: Encoder, desiredBufferCapacity: Int) {
self.encoder = encoder
self.desiredBufferCapacity = desiredBufferCapacity.nextPowerOf2()
}

public init(_ encoder: Encoder) {
self.encoder = encoder
self.desiredBufferCapacity = nil
}
}

Expand Down Expand Up @@ -817,4 +824,11 @@ extension MessageToByteHandler {
context.fireErrorCaught(error)
}
}

public func flush(context: ChannelHandlerContext) {
context.flush()
ali-ahsan-ali marked this conversation as resolved.
Show resolved Hide resolved
if let desiredBufferCapacity {
ali-ahsan-ali marked this conversation as resolved.
Show resolved Hide resolved
self.buffer?.shrinkBufferCapacity(to: desiredBufferCapacity)
}
}
}
33 changes: 33 additions & 0 deletions Tests/NIOCoreTests/ByteBufferTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1837,6 +1837,39 @@ class ByteBufferTest: XCTestCase {
XCTAssertEqual(0xaa, buffer.getInteger(at: 0, as: UInt8.self))
XCTAssertEqual(0, buffer2.readableBytes)
}

func testShrinkBufferCapacity() {
let desiredCapacity = 1024
var buffer = self.allocator.buffer(capacity: 512)

// For any item, it should not shrink buffer capacity to a value larger than the current buffer capacity
buffer.clear()
buffer.writeString("Any item")
XCTAssertFalse(buffer.shrinkBufferCapacity(to: 2048))
XCTAssertEqual(buffer.capacity, 512)

// If desired capacity are less than or equal to buffer capacity, should not shrink
buffer.clear()
buffer.writeString(String(repeating: "x", count: desiredCapacity))
XCTAssertEqual(buffer.capacity, 1024) // Before
XCTAssertFalse(buffer.shrinkBufferCapacity(to: desiredCapacity))
XCTAssertEqual(buffer.capacity, 1024) // After

// If desiredCapacity is less than readable bytes, do not shrink
buffer.clear()
buffer.writeString(String(repeating: "x", count: desiredCapacity + 1))
XCTAssertEqual(buffer.capacity, 2048)
XCTAssertFalse(buffer.shrinkBufferCapacity(to: desiredCapacity))
XCTAssertEqual(buffer.capacity, 2048)

// If desired capacity is greater than the readable bytes and less than buffer capacity, should shrink to desiredCapacity.nextPowerOf2Clamp
// Where desiredCapacity.nextPowerOf2Clamp == desiredCapacity as desiredCapacity should already be a power of 2 value
buffer.clear()
buffer.writeString(String(repeating: "x", count: desiredCapacity - 1))
XCTAssertEqual(buffer.capacity, 2048)
XCTAssertTrue(buffer.shrinkBufferCapacity(to: desiredCapacity))
XCTAssertEqual(buffer.capacity, 1024)
}

func testDumpBytesFormat() throws {
self.buf.clear()
Expand Down