.NET核心IQueryable Lambda内存泄漏

yhuiod9q  于 2023-01-31  发布在  .NET
关注(0)|答案(1)|浏览(171)

我正在对表中具有唯一索引的列使用如下lambda查询。对于每个请求,大约会发生8 - 12 kb的内存泄漏。
此方法大约每秒调用10-20次。

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;
    }
}

我知道我在不同的地方使用AsNoTracking。我做了实验。
一位朋友说:“数据库连接进程可能正在进行中,所以dispose不起作用”。
这太有意义了,我试过.ToList(),我试过Count(),但都不管用。
8-10 kb可能看起来很小,但正如我所说,当请求数量很高时,IIS中使用的内存可以在1-2小时内达到2 GB。
数据库模型是DbContext类,mobileQrTempler是表。我也不想创建另一个模型。实际上,我想通过直接从dbcontext拉取数据来防止可能的内存泄漏。但它又一次没有。顺便说一下,我用Jquery AJAX 在视图中调用了这个方法。所以实际上这个方法是在一个控制器中。而不是控制器。我想到了一个问题,控制器是否过载?控制器是否不适合被调用太多次?是否可能是太多的请求导致内存在控制器上累积?我知道你说“lambda查询没有问题”。我不这么认为。但是某处有一个问题。我将尝试另一个测试。我想通过制作一个API来添加这个方法,用1000 RPS试试。

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

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

}

主计长

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

    return Json(Ok());
}

}
AJAX 示例

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

Jquery AJAX 每4. 5秒调用一次这个方法,这个系统目前安装在大约100个客户端上,当我查看服务器的日志记录时,我看到每秒大约有7-8个请求。

disho6za

disho6za1#

我不认为这是内存泄漏。在.NET(像许多托管语言)中,垃圾收集器在必要时清理对象示例。尝试执行更多请求,您将看到内存使用稳定下来。
如果你想在调用控制器的操作时检查Web应用程序是否存在内存泄漏,你可以尝试添加一个中间件来强制垃圾收集器进行清理:

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

考虑在部署应用程序之前删除它,因为不建议手动调用垃圾收集器,但是当一个编码错误的应用程序有异常的内存使用时,它可以是一个快速的临时修复。
此外,ASP.NETCore应用程序默认以垃圾收集器服务器模式运行,在这种模式下,垃圾收集器工作较少,很少进行清理。
此模式的其他影响,内存分配的应用程序是从来没有释放。在服务器上,进程和内存的数量是固定的。这是浪费时间释放内存重新分配它以后,然后应用程序保持内存分配。更多信息在:

您可以通过在app.config(或web.config)中添加来禁用此行为:

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

建议在Web应用程序的内存使用情况发生变化时使用此选项。
离题,您可以通过以下方式优化EF查询:

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

然后查询将类似于:

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

并且EF核心将仅加载一个布尔值。

相关问题