grpc: Too many full GCs when receive big responses

I found that a lot of full GCs are run when the client receives big responses (about 100KB).

Here is an example code: https://gist.github.com/azyobuzin/7fee0a968a8780fc56b7e8a829c60d9b#file-grpcmemorytest-cs

In the example, the client will receive 100KB responses every 0.1 seconds.

I ran the code, profiling with CLR Profiler. Then I found that full(gen 2) GCs were run about every 3 seconds, and a lot of allocation happened in BatchContextSafeHandle.GetReceivedMessage.

when GCs happen

where allocations happen

The result of profiling: https://gist.github.com/azyobuzin/7fee0a968a8780fc56b7e8a829c60d9b#file-grpcmemorytest-log

I think the situation where full GCs are run many times is not good. I would suggest it use an object pool, for example System.Buffers.ArrayPool.

What version of gRPC and what language are you using?

gRPC C# 1.7.1 from NuGet

What operating system (Linux, Windows, …) and version?

Windows (.NET Framework 4.7)

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 1
  • Comments: 15 (9 by maintainers)

Most upvoted comments

@jtattermusch thank you! This work has significantly reduced our GC time! There is still one area causing large GC though, which is the fact that we can’t pass rented buffers from an ArrayPool to the final Grpc response because we don’t know when they will be released. I know other people have brought this up - is there any plan to support this? Or are there any good approaches to work around this limitation?

https://github.com/protocolbuffers/protobuf/pull/7351 has been merged. Once that feature gets release (and we add bindings for the new de-serialization API on the gRPC side), this issue can be marked as fixed.