当前位置:网站首页>Record the pit of NETCORE's memory surge

Record the pit of NETCORE's memory surge

2022-07-06 03:51:00 Xingzai 007

The project used Coldairarrow/EFCore.Sharding: Database Sharding For EFCore (github.com) This component , At first, it was used because the sub table was well made .

Because the project has been developing and testing , So there is a service memory has been soaring , Just restart , I got up after a long time . I have to say that Microsoft documents are really awesome

dotnet-counters Diagnostic tools - .NET CLI | Microsoft Docs

I first read this article , Without it , I won't go deep into Microsoft's diagnostic tools .

【.Net Core】 analysis .net core stay linux The memory occupation is too high -- Continuous updating - Zheng Lisai - Blog Garden (cnblogs.com)

The picture above shows System.Diagnostics.StackFrame The memory consumption is the highest , All the output information is analyzed later , It is found that the database outputs a lot of information ,... Locate that the sub table cannot be released, resulting in .

By downloading the sample code :

using EFCore.Sharding;
using EFCore.Sharding.Tests;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
using System.Threading.Tasks;

namespace Demo.DateSharding
{
    class Program
    {
        static async Task Main(string[] args)
        {
            DateTime startTime = DateTime.Now.AddMinutes(-5);
            ServiceCollection services = new ServiceCollection();
            // Configuration initialization 
            services.AddLogging(x =>
            {
                x.AddConsole();
            });
            services.AddEFCoreSharding(config =>
            {
                config.SetEntityAssemblies(typeof(Base_UnitTest).Assembly);

                // Add data sources 
                config.AddDataSource(Config.CONSTRING1, ReadWriteType.Read | ReadWriteType.Write, DatabaseType.SqlServer);

                // By minute 
                config.SetDateSharding<Base_UnitTest>(nameof(Base_UnitTest.CreateTime), ExpandByDateMode.PerMinute, startTime);
            });

            var serviceProvider = services.BuildServiceProvider();
            new EFCoreShardingBootstrapper(serviceProvider).StartAsync(default).Wait();

           
            for (int i = 0; i < 2000; i++)
            {
                using var scop = serviceProvider.CreateScope();
                var db = scop.ServiceProvider.GetService<IShardingDbAccessor>();
                var logger = scop.ServiceProvider.GetService<ILogger<Program>>();
                await db.InsertAsync(new Base_UnitTest
                {
                    Id = Guid.NewGuid().ToString(),
                    Age = 1,
                    UserName = Guid.NewGuid().ToString(),
                    CreateTime = DateTime.Now
                });
                DateTime time = DateTime.Now.AddMinutes(-2);
                var count = await db.GetIShardingQueryable<Base_UnitTest>()
                    .Where(x => x.CreateTime >= time)
                    .CountAsync();
                logger.LogWarning(" Current data volume :{Count}", count);
            }
            Console.ReadKey();
           
        }
    }
}
 using var scop = serviceProvider.CreateScope() If you create more than once , This memory continues to rise , Don't release .

 

 If you move this line of code out , Memory will be stable . Although inherited idisposiable , It was used using But it still won't release , It's a headache .  But if the following code is transformed into the above one, there will be no memory guarantee .
using EFCore.Sharding;
using EFCore.Sharding.Tests;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
using System.Threading.Tasks;

namespace Demo.HelloWorld
{
    class Program
    {
        static async Task Main(string[] args)
        {
            ServiceCollection services = new ServiceCollection();
            services.AddLogging(config =>
            {
                config.AddConsole();
            });
            services.AddEFCoreSharding(config =>
            {
                config.SetEntityAssemblies(typeof(Base_UnitTest).Assembly);

                config.UseDatabase(Config.SQLITE1, DatabaseType.SQLite);
            });
            var serviceProvider = services.BuildServiceProvider();
            new EFCoreShardingBootstrapper(serviceProvider).StartAsync(default).Wait();

            using var scop = serviceProvider.CreateScope();
            // Get the injection IDbAccessor You can perform all database operations 
            var db = scop.ServiceProvider.GetService<IDbAccessor>();
            var logger = scop.ServiceProvider.GetService<ILogger<Program>>();
            while (true)
            {
                await db.InsertAsync(new Base_UnitTest
                {
                    Age = 100,
                    CreateTime = DateTime.Now,
                    Id = Guid.NewGuid().ToString(),
                    UserId = Guid.NewGuid().ToString(),
                    UserName = Guid.NewGuid().ToString()
                });
                var count = await db.GetIQueryable<Base_UnitTest>().CountAsync();

                logger.LogWarning(" Current quantity :{Count}", count);

                await Task.Delay(1000);
            }
        }
    }
}
 It turned out IDbAccessor It was created through the factory , Don't pass service Inject . however IShardingDbAccessor It's through  services.AddScoped<IShardingDbAccessor, ShardingDbAccessor>() Injected into the service .

The solution to the project is to put

services.AddScoped<IShardingDbAccessor, ShardingDbAccessor>() Change to simple interest injection .
 

 

原网站

版权声明
本文为[Xingzai 007]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202132302320854.html