Внедрение зависимостей .NET Core: регистрация сервиса фабричным методом идет медленнее? - PullRequest
1 голос
/ 29 апреля 2019

Я думал, что регистрация сервиса фабричным методом будет быстрее (при вызове GetRequiredService<T>), потому что я сам создаю новые объекты. Однако на самом деле это немного медленнее.

Кто-нибудь знает почему?

Регистрация услуги по заводскому методу:

ServiceCollection services = new ServiceCollection();

services.AddTransient<IServiceXxx>(sp =>
    new ServiceXxx(new ServiceA(), new ServiceB())
);

Обычная регистрация:

ServiceCollection services = new ServiceCollection();

services.AddTransient<IServiceA, ServiceA>();
services.AddTransient<IServiceB, ServiceB>();
services.AddTransient<IServiceXxx, ServiceXxx>();

Результаты теста:

// sw1= 1619, sw2 (Factory)=1362
// sw1= 1191, sw2 (Factory)=1410
// sw1= 1020, sw2 (Factory)=1254
// sw1= 1024, sw2 (Factory)=1244
// sw1= 1039, sw2 (Factory)=1250
// sw1= 1024, sw2 (Factory)=1227
// sw1= 1037, sw2 (Factory)=1250
// sw1= 1023, sw2 (Factory)=1240
// sw1= 1009, sw2 (Factory)=1230
// sw1= 1042, sw2 (Factory)=1227

Полный код указан ниже:

using System;
using System.Diagnostics;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace FrameworkTest
{
[TestClass]
public class UnitTest1 : TestBase
{
    [TestMethod]
    public void TestMethod1()
    {
        long loopCount = 10L * 1000 * 1000;

        for (int i = 0; i < 10; i++)
        {
            var svcProvider1 = BuildSp();
            var svcProvider2 = BuildSpWithFactory();

            long sw1 = GetExecutionTime(svcProvider1, loopCount);
            long sw2 = GetExecutionTime(svcProvider2, loopCount);

            Console.WriteLine($"sw1={sw1}, sw2 (Factory)={sw2}");
        }

        // sw1= 1619, sw2 (Factory)=1362
        // sw1= 1191, sw2 (Factory)=1410
        // sw1= 1020, sw2 (Factory)=1254
        // sw1= 1024, sw2 (Factory)=1244
        // sw1= 1039, sw2 (Factory)=1250
        // sw1= 1024, sw2 (Factory)=1227
        // sw1= 1037, sw2 (Factory)=1250
        // sw1= 1023, sw2 (Factory)=1240
        // sw1= 1009, sw2 (Factory)=1230
        // sw1= 1042, sw2 (Factory)=1227
    }

    public IServiceProvider BuildSp()
    {
        ServiceCollection services = new ServiceCollection();

        services.AddTransient<IServiceA, ServiceA>();
        services.AddTransient<IServiceB, ServiceB>();
        services.AddTransient<IServiceXxx, ServiceXxx>();

        var svcProvider = services.BuildServiceProvider();
        return svcProvider;
    }

    public IServiceProvider BuildSpWithFactory()
    {
        ServiceCollection services = new ServiceCollection();

        services.AddTransient<IServiceXxx>(sp =>
            new ServiceXxx(new ServiceA(), new ServiceB())
        );

        var svcProvider = services.BuildServiceProvider();
        return svcProvider;
    }

    public long GetExecutionTime(IServiceProvider sp, long loopCount)
    {
        Stopwatch sw = Stopwatch.StartNew();
        for (int i = 0; i < loopCount; i++)
        {
            var svcX = sp.GetRequiredService<IServiceXxx>();
        }
        sw.Stop();
        return sw.ElapsedMilliseconds;
    }




    public interface IServiceA { }
    public interface IServiceB { }

    public interface IServiceXxx { }

    public class ServiceA : IServiceA { }
    public class ServiceB : IServiceB { }

    public class ServiceXxx : IServiceXxx
    {
        public ServiceXxx(IServiceA a, IServiceB b)
        {

        }
    }
}
...