Skip to content

Commit c52c0dc

Browse files
glbrnttpinlin168
authored andcommitted
Avoid CoWs (grpc#1530)
We didn't actually avoid a CoW here. We also don't need the 'modifying' workaround; the compiler is smarter now.
1 parent 50b2980 commit c52c0dc

File tree

1 file changed

+19
-74
lines changed

1 file changed

+19
-74
lines changed

Diff for: Sources/GRPC/HTTP2ToRawGRPCStateMachine.swift

+19-74
Original file line numberDiff line numberDiff line change
@@ -21,23 +21,6 @@ import NIOHTTP2
2121
struct HTTP2ToRawGRPCStateMachine {
2222
/// The current state.
2323
private var state: State = .requestIdleResponseIdle
24-
25-
/// Temporarily sets `self.state` to `._modifying` before calling the provided block and setting
26-
/// `self.state` to the `State` modified by the block.
27-
///
28-
/// Since we hold state as associated data on our `State` enum, any modification to that state
29-
/// will trigger a copy on write for its heap allocated data. Temporarily setting the `self.state`
30-
/// to `._modifying` allows us to avoid an extra reference to any heap allocated data and
31-
/// therefore avoid a copy on write.
32-
@inlinable
33-
internal mutating func withStateAvoidingCoWs<Action>(_ body: (inout State) -> Action) -> Action {
34-
var state: State = ._modifying
35-
swap(&self.state, &state)
36-
defer {
37-
swap(&self.state, &state)
38-
}
39-
return body(&state)
40-
}
4124
}
4225

4326
extension HTTP2ToRawGRPCStateMachine {
@@ -63,9 +46,6 @@ extension HTTP2ToRawGRPCStateMachine {
6346

6447
// Both streams are closed. This state is terminal.
6548
case requestClosedResponseClosed
66-
67-
// Not a real state. See 'withStateAvoidingCoWs'.
68-
case _modifying
6949
}
7050

7151
struct RequestOpenResponseIdleState {
@@ -867,21 +847,19 @@ extension HTTP2ToRawGRPCStateMachine {
867847
encoding: ServerMessageEncoding,
868848
normalizeHeaders: Bool
869849
) -> ReceiveHeadersAction {
870-
return self.withStateAvoidingCoWs { state in
871-
state.receive(
872-
headers: headers,
873-
eventLoop: eventLoop,
874-
errorDelegate: errorDelegate,
875-
remoteAddress: remoteAddress,
876-
logger: logger,
877-
allocator: allocator,
878-
responseWriter: responseWriter,
879-
closeFuture: closeFuture,
880-
services: services,
881-
encoding: encoding,
882-
normalizeHeaders: normalizeHeaders
883-
)
884-
}
850+
return self.state.receive(
851+
headers: headers,
852+
eventLoop: eventLoop,
853+
errorDelegate: errorDelegate,
854+
remoteAddress: remoteAddress,
855+
logger: logger,
856+
allocator: allocator,
857+
responseWriter: responseWriter,
858+
closeFuture: closeFuture,
859+
services: services,
860+
encoding: encoding,
861+
normalizeHeaders: normalizeHeaders
862+
)
885863
}
886864

887865
/// Receive request buffer.
@@ -890,16 +868,12 @@ extension HTTP2ToRawGRPCStateMachine {
890868
/// - endStream: Whether end stream was set.
891869
/// - Returns: Returns whether the caller should try to read a message from the buffer.
892870
mutating func receive(buffer: inout ByteBuffer, endStream: Bool) -> ReceiveDataAction {
893-
return self.withStateAvoidingCoWs { state in
894-
state.receive(buffer: &buffer, endStream: endStream)
895-
}
871+
self.state.receive(buffer: &buffer, endStream: endStream)
896872
}
897873

898874
/// Send response headers.
899875
mutating func send(headers: HPACKHeaders) -> Result<HPACKHeaders, Error> {
900-
return self.withStateAvoidingCoWs { state in
901-
state.send(headers: headers)
902-
}
876+
self.state.send(headers: headers)
903877
}
904878

905879
/// Send a response buffer.
@@ -908,33 +882,25 @@ extension HTTP2ToRawGRPCStateMachine {
908882
allocator: ByteBufferAllocator,
909883
compress: Bool
910884
) -> Result<(ByteBuffer, ByteBuffer?), Error> {
911-
return self.withStateAvoidingCoWs { state in
912-
state.send(buffer: buffer, allocator: allocator, compress: compress)
913-
}
885+
self.state.send(buffer: buffer, allocator: allocator, compress: compress)
914886
}
915887

916888
/// Send status and trailers.
917889
mutating func send(
918890
status: GRPCStatus,
919891
trailers: HPACKHeaders
920892
) -> HTTP2ToRawGRPCStateMachine.SendEndAction {
921-
return self.withStateAvoidingCoWs { state in
922-
state.send(status: status, trailers: trailers)
923-
}
893+
self.state.send(status: status, trailers: trailers)
924894
}
925895

926896
/// The pipeline has been configured with a service provider.
927897
mutating func pipelineConfigured() -> PipelineConfiguredAction {
928-
return self.withStateAvoidingCoWs { state in
929-
state.pipelineConfigured()
930-
}
898+
self.state.pipelineConfigured()
931899
}
932900

933901
/// Try to read a request message.
934902
mutating func readNextRequest(maxLength: Int) -> ReadNextMessageAction {
935-
return self.withStateAvoidingCoWs { state in
936-
state.readNextRequest(maxLength: maxLength)
937-
}
903+
self.state.readNextRequest(maxLength: maxLength)
938904
}
939905
}
940906

@@ -959,9 +925,6 @@ extension HTTP2ToRawGRPCStateMachine.State {
959925
.requestClosedResponseOpen,
960926
.requestClosedResponseClosed:
961927
preconditionFailure("Invalid state: response stream opened before pipeline was configured")
962-
963-
case ._modifying:
964-
preconditionFailure("Left in modifying state")
965928
}
966929
}
967930

@@ -1005,9 +968,6 @@ extension HTTP2ToRawGRPCStateMachine.State {
1005968
.requestClosedResponseIdle,
1006969
.requestClosedResponseOpen:
1007970
preconditionFailure("Invalid state: \(self)")
1008-
1009-
case ._modifying:
1010-
preconditionFailure("Left in modifying state")
1011971
}
1012972
}
1013973

@@ -1049,9 +1009,6 @@ extension HTTP2ToRawGRPCStateMachine.State {
10491009

10501010
case .requestClosedResponseClosed:
10511011
return .nothing
1052-
1053-
case ._modifying:
1054-
preconditionFailure("Left in modifying state")
10551012
}
10561013
}
10571014

@@ -1085,9 +1042,6 @@ extension HTTP2ToRawGRPCStateMachine.State {
10851042
case .requestOpenResponseClosed,
10861043
.requestClosedResponseClosed:
10871044
return .none
1088-
1089-
case ._modifying:
1090-
preconditionFailure("Left in modifying state")
10911045
}
10921046
}
10931047

@@ -1111,9 +1065,6 @@ extension HTTP2ToRawGRPCStateMachine.State {
11111065
.requestClosedResponseOpen,
11121066
.requestClosedResponseClosed:
11131067
return .failure(GRPCError.AlreadyComplete())
1114-
1115-
case ._modifying:
1116-
preconditionFailure("Left in modifying state")
11171068
}
11181069
}
11191070

@@ -1150,9 +1101,6 @@ extension HTTP2ToRawGRPCStateMachine.State {
11501101
case .requestOpenResponseClosed,
11511102
.requestClosedResponseClosed:
11521103
return .failure(GRPCError.AlreadyComplete())
1153-
1154-
case ._modifying:
1155-
preconditionFailure("Left in modifying state")
11561104
}
11571105
}
11581106

@@ -1183,9 +1131,6 @@ extension HTTP2ToRawGRPCStateMachine.State {
11831131
case .requestOpenResponseClosed,
11841132
.requestClosedResponseClosed:
11851133
return .failure(GRPCError.AlreadyComplete())
1186-
1187-
case ._modifying:
1188-
preconditionFailure("Left in modifying state")
11891134
}
11901135
}
11911136
}

0 commit comments

Comments
 (0)