Skip to content

NET 8.0 Preview 7 Performance Regression: ActivatorUtilities.CreateInstance #91186

Closed

Description

@Jakimar

Description

I was checking new behavior for "ActivatorUtilities.CreateInstance" in NET 8.0 and noticed some perfomance regression when invoked for class with not empty construcor, as i can see something changed between "Preview 6" and "Preview 7", it's slighly better in last daily build "rc.2.23426.4" but still much worse than NET7.0 .

public class Tester
{
    private static IServiceProvider _spProvider;

    public Tester()
    {
        var sc = new ServiceCollection();
        sc.AddScoped<A>();
        sc.AddScoped<B>();
        sc.AddScoped<C>();
        _spProvider = sc.BuildServiceProvider();
    }
    
    public A? CreateA()
    {
        var scope = _spProvider.CreateScope();
        return ActivatorUtilities.CreateInstance<A>(scope.ServiceProvider);
    }
    
    public B? CreateB()
    {
        var scope = _spProvider.CreateScope();
        return ActivatorUtilities.CreateInstance<B>(scope.ServiceProvider);
    }
    
    public C? CreateC()
    {
        var scope = _spProvider.CreateScope();
        return ActivatorUtilities.CreateInstance<C>(scope.ServiceProvider);
    }
}

    public class A
    { }

    public class B
    {
        private readonly A _a;

        public B(A a)
        {
            _a = a;
        }
    }

    public class C
    {
        private readonly B _b;
        private readonly B _b1;
        private readonly B _b2;
        private readonly B _b3;
        private readonly B _b4;
        private readonly B _b5;
        
        public C(B b, B b1, B b2, B b3, B b4, B b5)
        {
            _b = b;
            _b1 = b1;
            _b2 = b2;
            _b3 = b3;
            _b4 = b4;
            _b5 = b5;
        }
    }

Configuration

BenchmarkDotNet v0.13.7, Windows 10 (10.0.19044.3086/21H2/November2021Update)
11th Gen Intel Core i5-11600K 3.90GHz, 1 CPU, 12 logical and 6 physical cores
.NET SDK 8.0.100-rc.2.23425.18
  [Host]                  : .NET 7.0.1 (7.0.122.56804), X64 RyuJIT AVX2
  7.0.0                   : .NET 7.0.1 (7.0.122.56804), X64 RyuJIT AVX2
  8.0.0-preview.6.23329.7 : .NET 8.0.0 (8.0.23.42311), X64 RyuJIT AVX2
  8.0.0-preview.7.23375.6 : .NET 8.0.0 (8.0.23.42311), X64 RyuJIT AVX2
  8.0.0-rc.2.23426.4      : .NET 8.0.0 (8.0.23.42311), X64 RyuJIT AVX2

Regression?

Data

Method Runtime NuGetReferences Mean Error StdDev Ratio
CreateA .NET 7.0 Microsoft.Extensions.DependencyInjection 7.0.0 122.1 ns 2.05 ns 1.92 ns baseline
CreateA .NET 8.0 Microsoft.Extensions.DependencyInjection 8.0.0-preview.6.23329.7 116.8 ns 2.33 ns 2.50 ns -4%
CreateA .NET 8.0 Microsoft.Extensions.DependencyInjection 8.0.0-preview.7.23375.6 113.6 ns 1.54 ns 1.44 ns -7%
CreateA .NET 8.0 Microsoft.Extensions.DependencyInjection 8.0.0-rc.2.23426.4 119.0 ns 2.42 ns 2.69 ns -3%
CreateB .NET 7.0 Microsoft.Extensions.DependencyInjection 7.0.0 220.3 ns 3.31 ns 3.10 ns baseline
CreateB .NET 8.0 Microsoft.Extensions.DependencyInjection 8.0.0-preview.6.23329.7 218.9 ns 3.83 ns 3.39 ns -1%
CreateB .NET 8.0 Microsoft.Extensions.DependencyInjection 8.0.0-preview.7.23375.6 480.0 ns 3.31 ns 2.76 ns +118%
CreateB .NET 8.0 Microsoft.Extensions.DependencyInjection 8.0.0-rc.2.23426.4 402.6 ns 4.53 ns 4.24 ns +83%
CreateC .NET 7.0 Microsoft.Extensions.DependencyInjection 7.0.0 522.9 ns 4.21 ns 3.73 ns baseline
CreateC .NET 8.0 Microsoft.Extensions.DependencyInjection 8.0.0-preview.6.23329.7 494.1 ns 3.49 ns 2.91 ns -5%
CreateC .NET 8.0 Microsoft.Extensions.DependencyInjection 8.0.0-preview.7.23375.6 2,489.0 ns 26.57 ns 24.85 ns +376%
CreateC .NET 8.0 Microsoft.Extensions.DependencyInjection 8.0.0-rc.2.23426.4 1,604.6 ns 26.34 ns 23.35 ns +207%

Activity

  1. ghost added
    untriagedNew issue has not been triaged by the area owner
    on Aug 28, 2023
  2. ghost added
    needs-area-labelAn area label is needed to ensure this gets routed to the appropriate area owners
    on Aug 28, 2023
  3. stephentoub commented on Aug 28, 2023

    @stephentoub
    Member
  4. steveharter commented on Aug 28, 2023

    @steveharter
    Contributor

    Currently verifying this issue to see if same as reported in #89104

  5. removed
    needs-area-labelAn area label is needed to ensure this gets routed to the appropriate area owners
    on Aug 28, 2023
  6. steveharter commented on Aug 28, 2023

    @steveharter
    Contributor

    This is a regression from the "keyed services" feature due to reading custom attributes. In this case, it is the FromKeyedServicesAttribute per ParameterInfo which in a quick prototype showed that caching this in a dictionary will get very close to 7.0 perf. Working on this now.

  7. added
    needs-further-triageIssue has been initially triaged, but needs deeper consideration or reconsideration
    and removed
    untriagedNew issue has not been triaged by the area owner
    on Aug 28, 2023
  8. steveharter commented on Aug 29, 2023

    @steveharter
    Contributor

    Using a dictionary to hold the ParameterInfo per above does get us back to almost 7.0, but doing a full cache on all of the ConstructorInfo state yields a much better result:

    7.0:

    Method Mean Error StdDev Median Min Max Gen0 Allocated
    CreateA 147.9 ns 1.07 ns 0.95 ns 148.1 ns 146.0 ns 149.3 ns 0.0198 208 B
    CreateB 249.1 ns 2.42 ns 2.15 ns 249.7 ns 245.1 ns 251.8 ns 0.0405 432 B
    CreateC 566.5 ns 2.64 ns 2.21 ns 567.0 ns 560.4 ns 569.2 ns 0.0610 648 B

    8.0:

    Method Mean Error StdDev Median Min Max Gen0 Allocated
    CreateA 134.5 ns 1.13 ns 1.00 ns 134.5 ns 133.2 ns 136.2 ns 0.0196 208 B
    CreateB 473.9 ns 6.06 ns 5.06 ns 471.3 ns 467.9 ns 481.4 ns 0.0386 456 B
    CreateC 1,929.6 ns 28.26 ns 25.05 ns 1,927.4 ns 1,895.7 ns 1,978.6 ns 0.0484 600 B

    After:

    Method Mean Error StdDev Median Min Max Gen0 Allocated
    CreateA 63.17 ns 1.224 ns 1.144 ns 62.87 ns 61.90 ns 64.92 ns 0.0167 176 B
    CreateB 156.20 ns 1.943 ns 1.722 ns 155.95 ns 153.78 ns 159.85 ns 0.0374 392 B
    CreateC 444.48 ns 3.875 ns 3.435 ns 443.92 ns 438.29 ns 451.37 ns 0.0461 496 B
  9. steveharter commented on Aug 29, 2023

    @steveharter
    Contributor

    Setting to v9; will get feedback on whether to port to v8.

  10. added this to the 9.0.0 milestone on Aug 29, 2023
  11. removed
    needs-further-triageIssue has been initially triaged, but needs deeper consideration or reconsideration
    on Aug 29, 2023
  12. self-assigned this
    on Aug 29, 2023
  13. ghost added
    in-prThere is an active PR which will close this issue when it is merged
    on Aug 29, 2023
  14. changed the title [-]NET 8.0 Preview 7 Perfomance Regression: ActivatorUtilities.CreateInstance[/-] [+]NET 8.0 Preview 7 Performance Regression: ActivatorUtilities.CreateInstance[/+] on Aug 29, 2023
  15. stephentoub commented on Aug 30, 2023

    @stephentoub
    Member

    Setting to v9; will get feedback on whether to port to v8.

    I think it'd be good to fix this for 8.

  16. modified the milestones: 9.0.0, 8.0.0 on Sep 1, 2023
  17. ghost removed
    in-prThere is an active PR which will close this issue when it is merged
    on Sep 11, 2023
  18. stephentoub commented on Sep 11, 2023

    @stephentoub
    Member

    Reopening to track backport.

  19. steveharter commented on Sep 12, 2023

    @steveharter
    Contributor

    Closing; fixed in backport

  20. ghost locked as resolved and limited conversation to collaborators on Oct 12, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions