Я думал, что регистрация сервиса фабричным методом будет быстрее (при вызове 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)
{
}
}
}