Home > OS >  .NET Core IQueryable Lambda Memory Leak
.NET Core IQueryable Lambda Memory Leak

Time:01-29

I am using a lambda query as below on a column with a Unique index in the table. For each request, approximately 8 -12 kb memory leak occurs.

This method will be called approximately 10-20 times per second.

bool KontrolKullanildi(string QrCode)
{
    using (EmlesCore.Models.Database db = new EmlesCore.Models.Database())
    {                
        using (var o = db.mobilQrTempler.AsNoTracking().Where(f => f.CryptoKod == QrCode && f.Kullanildi).AsNoTracking().FirstOrDefault())
        {
            if (o != null)
            {
                return true;
            }
        }

        return false;
    }
}

Memory status

Code

I know I use AsNoTracking in different places. I made experiments.

A friend said, "The database connection process may be in progress, so dispose won't work".

This made so much sense. I've tried .ToList(), I've tried Count(), but nothing has worked.

8-10 kb may seem small. But as I said, when the number of requests is high, the memory used in IIS can be 2 GB in 1-2 hours.

CodePudding user response:

I don't think it a memory leak. In .NET (like many managed language), the garbage collector clean the object instance when it's necessary. Try do more request and you will see the memory usage stabilize.

If you want check if the web application has a memory leak when a controller's action is called, you can try to add a middleware that force the garbage collector to do the cleaning :

var builder = WebApplication.CreateBuilder(args);
...
var app = builder.Build();
app.Use(async (context, next) =>
{
    await next(context);
    Sytem.GC.Collect();
});
...
app.Run();

Think to remove this before to deploy the application, because it isn't recommended to call manually the garbage collector. But it can be a quick temporary fix when a bad coded application has a abnormal memory usage.


Moreover, a ASP.NET Core application run by default in garbage collector server mode. In this mode, the garbage collector work less and the cleaning is rarely done.

Other effect of this mode, the memory allocate by the application is never released. On server, the number of process and memory is fixed. It's a waste of time to release the memory to reallocate it later, then the application keep the memory allocated. More information in :

You can disable this behavior by adding in in app.config (or web.config) :

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <runtime>
        <gcServer enabled="false"/>
    </runtime>
</configuration>

It's recommended when a web application has a memory usage varying.


Off topic, you can optimize the EF query by :

bool KontrolKullanildi(string QrCode)
{
    using (EmlesCore.Models.Database db = new EmlesCore.Models.Database())
    {
        return db.mobilQrTempler.Any(f => f.CryptoKod == QrCode && f.Kullanildi);
    }
}

Then the query will be like :

SELECT TOP 1 1
FROM mobilQrTempler
WHERE CryptoKod = @QrCode AND Kullanildi = 1

and EF Core will load just one boolean.

CodePudding user response:

@vernou,

Database Model is DbContext class. and mobileQrTempler is Table. I also didn't want to create another model. Actually, I wanted to prevent possible memory leak by pulling data directly from dbcontext. But again it didn't. By the way, I call this method in view with Jquery Ajax. So actually this method is inside a controller. Not apicontroller. A question comes to my mind, is there an overload on the controller? Is the controller not suitable to be called too many times ? Could it be that too many requests are causing memory to accumulate on the controller? I know you said "No problem with lambda query". I don't think so. But Somewhere there is a problem. I'll try another test. I want to try it with 1000 RPS by adding this method by making a rest api.

public class Database:DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(Utils.DbConnectionString());
        
    }

public DbSet<mobileQrTemp> mobilQrTempler { get; set; }

}

Controller

public class QrGirisCikisQrKontrol : Controller{
public async Task<JsonResult> GetQrCode(string parameters)
    {
    if (KontrolKullanildi(QrFiltre))
        {
            return Json(QrCodeOlusturDondur(Parameters));
        }

    return Json(Ok());
}

}

Sample Ajax

$.ajax({
        type: "GET",
        url: "@Url.Action("GetQrCode","QrGirisCikisQrKontrol")",
        data: params,
        success: function (result) ..............

Jquery Ajax calls this method once every 4.5 seconds. This system is installed on about 100 clients at the moment. When I look at the log records of the server, I see that there are approximately 7-8 requests per second.

  • Related