-
Notifications
You must be signed in to change notification settings - Fork 11.1k
C# memory leak with multiple channels #14021
Copy link
Copy link
Closed
Description
- Grpc.Core v1.8.0 and 1.8.3 behave very badly; Grpc.Core v1.7.3 is somewhat better (details below)
- Windows 10
Simple repro using Google.Cloud.Speech.V1 library just for the generated protos and gRPC code:
using Google.Apis.Auth.OAuth2;
using Google.Cloud.Speech.V1;
using Grpc.Auth;
using Grpc.Core;
using System;
public class Test
{
public static void Main(string[] args)
{
GoogleCredential googleCredential = GoogleCredential.GetApplicationDefault();
ChannelCredentials channelCreds = googleCredential.ToChannelCredentials();
for (int i = 0; i < 100; ++i)
{
var channel = new Channel(SpeechClient.DefaultEndpoint.Host, channelCreds);
var speech = new Speech.SpeechClient(channel);
var call = speech.StreamingRecognize();
call.RequestStream.CompleteAsync().Wait();
call.ResponseStream.MoveNext(System.Threading.CancellationToken.None).Wait();
channel.ShutdownAsync().Wait();
Console.WriteLine($"{i}: {GC.GetTotalMemory(true)}");
}
}
}Project file:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Google.Cloud.Speech.V1" Version="1.0.0" />
<PackageReference Include="Grpc.Core" Version="1.8.3" />
</ItemGroup>
</Project>Output when using Grpc.Core v1.7.x:
0: 376984
1: 382392
2: 382392
3: 382960
4: 382960
5: 382960
6: 382960
7: 382960
8: 382960
9: 382960
(stable)
When using Grpc.Core v1.8.x:
0: 461312
1: 553512
2: 640344
3: 728456
4: 815368
5: 902816
6: 990232
7: 1077648
8: 1164728
9: 1250880
(keeps increasing)
Now even 1.7.x isn't perfect: if you comment out the call to call.ResponseStream.MoveNext(System.Threading.CancellationToken.None).Wait();, there's still a small leak, although it's much better than with 1.8.x:
0: 376976
1: 382504
2: 383136
3: 383280
4: 383424
5: 383648
6: 383792
7: 383936
8: 384080
9: 384224
Using a single channel instead of multiple channels avoids the leak even with 1.8.x, and even without calling MoveNext() to observe the end of the stream.
Reactions are currently unavailable