Browse Source

Avoid an error allocation in the server stream handler (#1970)

Motivation:

Existential errors unconditionally allocate. In the server stream
handler a promise is failed on tear down via an API which takes an
existential error. This means the handler always allocates, even if the
promise has been completed.

Modifications:

- Statically allocate the error as an existential

Result:

Fewer allocations
George Barnett 1 year ago
parent
commit
9b26d7812a
1 changed files with 8 additions and 6 deletions
  1. 8 6
      Sources/GRPCHTTP2Core/Server/GRPCServerStreamHandler.swift

+ 8 - 6
Sources/GRPCHTTP2Core/Server/GRPCServerStreamHandler.swift

@@ -39,6 +39,13 @@ final class GRPCServerStreamHandler: ChannelDuplexHandler, RemovableChannelHandl
 
   private let methodDescriptorPromise: EventLoopPromise<MethodDescriptor>
 
+  // Existential errors unconditionally allocate, avoid this per-use allocation by doing it
+  // statically.
+  private static let handlerRemovedBeforeDescriptorResolved: any Error = RPCError(
+    code: .unavailable,
+    message: "RPC stream was closed before we got any Metadata."
+  )
+
   init(
     scheme: GRPCStreamStateMachineConfiguration.Scheme,
     acceptedEncodings: CompressionAlgorithmSet,
@@ -159,12 +166,7 @@ extension GRPCServerStreamHandler {
 
   func handlerRemoved(context: ChannelHandlerContext) {
     self.stateMachine.tearDown()
-    self.methodDescriptorPromise.fail(
-      RPCError(
-        code: .unavailable,
-        message: "RPC stream was closed before we got any Metadata."
-      )
-    )
+    self.methodDescriptorPromise.fail(Self.handlerRemovedBeforeDescriptorResolved)
   }
 
   func channelInactive(context: ChannelHandlerContext) {