C# ASP.NET核心中的SQLite在每次调用中使用越来越多的RAM

C# ASP.NET核心中的SQLite在每次调用中使用越来越多的RAM,c#,sqlite,asp.net-core,asp.net-web-api,sqlite-net,C#,Sqlite,Asp.net Core,Asp.net Web Api,Sqlite Net,从SQLite数据库返回大量数据的查询使用从未发布过的RAM。RAM的使用量比数据库大很多倍,最终导致Windows内存不足错误和不稳定 此示例使用Visual Studio 2019中的ASP.NET核心Web应用程序模板显示了该问题。我用此代码替换默认的WeatherForecastController public class WeatherForecastController : ControllerBase { [HttpGet] public

从SQLite数据库返回大量数据的查询使用从未发布过的RAM。RAM的使用量比数据库大很多倍,最终导致Windows内存不足错误和不稳定

此示例使用Visual Studio 2019中的ASP.NET核心Web应用程序模板显示了该问题。我用此代码替换默认的WeatherForecastController

public class WeatherForecastController : ControllerBase
    {
        [HttpGet]
        public IEnumerable<int> GetAsync()
        {
            // create a 450MB database for testing (on first run only).
            if (System.IO.File.Exists("BigDatabase.db") == false) {
                using (SQLiteConnection db = new SQLiteConnection("BigDatabase.db"))
                {
                    db.CreateTable<NumbersAndText>();
                    List<NumbersAndText> ListOfMadeUpDataToInsertIntoDatabase = new List<NumbersAndText>();
                    for (int i = 0; i < 10000; i++)
                    {
                        NumbersAndText nat = new NumbersAndText()
                        {
                            Number = i,
                            BigBlockOfText = string.Concat(Enumerable.Repeat("Lots of text repeated over and over again.", 1000))
                        };
                        ListOfMadeUpDataToInsertIntoDatabase.Add(nat);
                    }
                    db.InsertAll(ListOfMadeUpDataToInsertIntoDatabase);
                }
            }

            // Take a lot of data from the database.
            // The process uses 500MB the first time the controller is fired. 900MB after the second time. 1.2GB, 1.3GB, etc...
            // After 15 calls the process is using 3.4GB of RAM.
            // Garbage Collection reduces this to around 2GB, at which point RAM use is stable. But this is now x5 the size of the database in RAM.
            // With a larger example this quickly fills all RAM and triggers the Windows out of memory killer. 
            List<NumbersAndText> Orgs;
            using (SQLiteConnection db = new SQLiteConnection("BigDatabase.db"))
            {
                Orgs = new List<NumbersAndText>(db.Table<NumbersAndText>().Take(5000));
            }

            // return just the numbers
            return Orgs.Select(x => x.Number);            
        }
    }
    public class NumbersAndText
    {
        public int Number { get; set; }
        public string BigBlockOfText { get; set; }
    }
公共类WeatherForecastController:ControllerBase
{
[HttpGet]
公共IEnumerable GetAsync()
{
//为测试创建一个450MB的数据库(仅在第一次运行时)。
if(System.IO.File.Exists(“BigDatabase.db”)==false){
使用(SQLiteConnection db=newsqliteconnection(“BigDatabase.db”))
{
db.CreateTable();
List ListOfMadeUpdateToInsertintoDatabase=新列表();
对于(int i=0;i<10000;i++)
{
NumbersAndText nat=新NumbersAndText()
{
编号=i,
BigBlockOfText=string.Concat(Enumerable.Repeat(“一次又一次重复的大量文本。”,1000))
};
添加(nat);
}
db.InsertAll(ListofMadeUpdateToInsertIntoDatabase);
}
}
//从数据库中获取大量数据。
//该进程在第一次启动控制器时使用500MB。第二次启动后使用900MB。1.2GB、1.3GB等。。。
//在15次调用之后,进程将使用3.4GB的RAM。
//垃圾收集将其减少到2GB左右,此时RAM的使用是稳定的。但现在这是RAM中数据库大小的5倍。
//在一个更大的例子中,这会迅速填满所有RAM并触发Windows内存不足杀手。
列出组织;
使用(SQLiteConnection db=newsqliteconnection(“BigDatabase.db”))
{
Orgs=新列表(db.Table().Take(5000));
}
//只返回数字
返回组织选择(x=>x.Number);
}
}
公共课号和课文
{
公共整数{get;set;}
公共字符串BigBlockOfText{get;set;}
}
在本例中,我使用该库处理SQLite数据库,但使用EFCore可以重现问题


我很确定我在做一些非常愚蠢的事情。但是我不知道是什么。

使用Visual Studio内置的分析工具来获取和分析内存快照:谢谢Ian。不幸的是,我做了很多这样的事情,但没有多大帮助。本机、混合以及本机和混合内存诊断都将我带到了同一个地方。我比较了每次调用前后的堆,但是从来没有足够的额外对象来解释这一点。使用Visual Studio的内置分析工具来获取和分析内存快照:谢谢Ian。不幸的是,我做了很多这样的事情,但没有多大帮助。本机、混合以及本机和混合内存诊断都将我带到了同一个地方。我比较了每次调用前后的堆,但从来没有足够的额外对象来解释这一点。