首次使用 protobuf-net c# 访问 gRPC 端点时性能缓慢
Posted
技术标签:
【中文标题】首次使用 protobuf-net c# 访问 gRPC 端点时性能缓慢【英文标题】:Performance slowness while hitting gRPC endpoints first time using protobuf-net c# 【发布时间】:2021-09-07 14:50:57 【问题描述】:我有一个使用 .NET Core 3.1 的 protobuf-net.gRPC 运行的 gRPC 服务器。它在后台使用 ASP.NET Core 框架和 Kestrel 来运行 HTTP 服务器。我注意到,与在同一端点上的后续调用相比,第一次在此服务器上命中的 gRPC 端点在 ASP NET Core 中间件中花费的时间要多得多。
Time taken from
Microsoft.AspNetCore.Routing.EndpointMiddleware[ExecutedEndPoint] : Executing endpoint 'gRPC - /grpc.....'
Until hitting the actual endpoint function in my gRPC server
第一次花费的时间相当长,大约 30-40 Ma,而随后对同一端点的调用大约是 1-2 ms。
这是因为 JIT 编译器是从 IL->Native 代码编译的吗?如果是这样,除了强制调用端点等显而易见的方法之外,还有其他方法可以解决这个首次性能问题吗?
问候
【问题讨论】:
第一个请求比后续请求花费更长的时间对我来说并不奇怪。我猜这只是 gRPC 服务器端堆栈的热身。此外,这可能不是 gRPC 特定的事情,当第一次使用 ASP.NET 核心中的新 HTTP/2 处理程序时,它的行为可能类似。我在这里找到了类似的讨论:github.com/dotnet/aspnetcore/issues/17985(这可能会给你你需要的答案)。 【参考方案1】:这可能是由于 gRPC 设计造成的,因为在发出第一个 RPC 调用之前不会建立通道的连接。
这 30-40 毫秒可能用于打开 TCP 连接 + SSL 握手 + HTTP/2 设置帧交换。以下 RPC 调用重用此通道/连接,因此没有此开销。
对于 Java,有一个实验性 API getState,客户端可以在创建通道后立即使用 requestConnection = true 参数调用它以启动连接。不确定它是否在 C# 中可用。
【讨论】:
我看到这 30-40ms 不是特定于客户端的。这是第一次在 gRPC 服务器上命中特定端点时发生。因此,如果我有 2 个端点 - /grpc/endpoint1、/grpc/endpoint2,首先调用 /grpc/endpoint1 和 /grpc/endpoint2 会产生 30-40 毫秒。此外,如果客户端 1 调用 /grpc/endpoint1 需要 30-40 毫秒,如果客户端 2 调用 /grpc/endpoint1 在此之后只需要几毫秒。所以这不是特定于客户的以上是关于首次使用 protobuf-net c# 访问 gRPC 端点时性能缓慢的主要内容,如果未能解决你的问题,请参考以下文章
protobuf-net 不使用私有设置器序列化 C# 属性
使用 C# 中的 ProtoBuf-Net 库将类数据保存到加密文件