简体   繁体   中英

Discovering Memory Leaks in .NET Core using PerfView

I have been trying to track down (what appears to be) a memory leak in an ASP.NET Core application running in Azure. I collected a DMP at the start of the application and a DMP when the memory was at it's peak right before it stalled out and crashed. I am trying to decipher the DMP files using PerfView. I loaded the first dump in, then the second and did a diff. The output of the "By Name" tab looks like this: DMP 的差异

So, question one is: Am I reading this right? Is this telling me there are 18,501 instances of HttpClient? If so, holy crap.

I went in to the "RefTree" tab and this is what I see there: 参考树 Sure enough the HttpClient that seems to be taking the bulk is from the LGAuthLib which is my library.

So, what I don't understand is, that HttpClient is a static object allocated once in a static constructor in that class library and then used everywhere. How is it possible to allocate 18,000 of them? Could 18,000 class libraries that house the static object exist? I don't know how that's possible since that object is allocated in a DI singleton.

This is why I am not 100% sure i am reading this Diff correctly. I just can't figure out how that could possibly be leaking.

For the professionals out there who have stared at these things, are you 100% certain the HttpClient object is leaking?

For completeness sake, here is how I am using the HttpClient object:

public async Task<string[]> GetRolesForUserByUserNameAsync(string strUser)
{
    var reqParams = new HttpRequestMessage(HttpMethod.Post, new UriBuilder(_config.ServerUri)
    {
        Path = EndpointGetRolesForUserByMicroService
    }.Uri);
    reqParams.Headers.Add("MicroService", CreateMicroServiceHeaderValue(EndpointGetRolesForUserByMicroService));
    reqParams.Content = HttpClientExtensions.JsonContent(new { userName = strUser });

    using (var resp = await _httpClient.SendAsync(reqParams).ConfigureAwait(false))
    {
        resp.EnsureSuccessStatusCode();
        return (await resp.Content.ReadAsJsonAsync<string>().ConfigureAwait(false)).Split(',');
    }
}

This is how it's being allocated:

public sealed class AuthService
{
    private static readonly HttpClient _httpClient;

    static AuthService()
    {
        _httpClient = new HttpClient();
    }
}

Migrating to .NET Core 3.0+ fixed this. It must have been an issue in the framework.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM