Even with a very simple request my c# api gets filled with unnecessary byte[] strings etc. and i really can't find anywhere where i think there can be a memory leak.
a little description:
The method collects all notebooks from a user and returns them.
It recognizes the user by the BearerToken.
Here is the code that is called, and yet per request several kb more ram is consumed and never released:
GetCurrentUser:
public static async Task<UserModel?> GetCurrentUser(DataBaseContext _db, string bearerToken)
{
//get from the bearer token the username
//create jwt token
var token = new JwtSecurityToken(jwtEncodedString: bearerToken);
//get the expiry from the token
var userName = token.Claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier)?.Value;
//get the whole user form the db
var user = _db.User
.Include(x => x.Invoices)
.Include(x => x.Notebook)
.Include(x => x.Logins)
.FirstOrDefaultAsync(x => x.Username == userName);
return await user;
}
GetCurrentUser & GetAll
private async Task<UserModel?> GetCurrentUser()
{
// Get the bearer token from the header
var bearerToken = HttpContext.Request.Headers["bearerToken"].ToString();
var user = await UserCore.GetCurrentUser(_db, bearerToken);
return user;
}
[HttpGet]
[Route("GetAll")]
public async Task<IActionResult> GetAll()
{
//set the users traceId
Guid traceId = Guid.NewGuid();
//get the user
var user = await GetCurrentUser();
if (user == null)
return new BadRequestObjectResult(ResponseMgr.CreateResponse(400, traceId, "The user does not exist"));
//get all notes
var notes = user.Notebook.ToList();
//return all notes
return new OkObjectResult(ResponseMgr.CreateResponse(200, traceId, "All notes", new Dictionary<string, object> { { "notes", notes } }));
}
this is one of the things i don't understand, this is the list with "duplicate strings", first column says "value", second "wasted" and third "count" and at the bottom "total"
The thing is, the emojis are content/value of one the notebook, but why does it keep the data and not release them after the request, so to sum up I found the leak but not where it happens.
All in one, I can't find the location, and if I make the request 50 times, then the API consumes several MB of ram and they will release the even the GC can't do that.
your code have another problem too. when username
null, not need check it the query for null
member just need forexample return it the null
you use more .Include()
, If one of them is a large amount of data, you will have problems (you return List
items, try take there data with another and better query )
use AsNoTracking()
means:
returns a new query and the entities aren't saved in cache, means that doesn't have tracking, the queries will read from database origin but won't saved in the context