Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<PlatformTarget>$([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture)</PlatformTarget>
<CodeAnalysisRuleSet>../../build/Test.ruleset</CodeAnalysisRuleSet>
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
Expand All @@ -10,7 +10,7 @@
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.15.6" />
<PackageReference Include="BenchmarkDotNet" Version="0.15.8" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Autofac.Benchmarks\Autofac.Benchmarks.csproj" />
Expand Down
22 changes: 13 additions & 9 deletions bench/Autofac.Benchmarks/Autofac.Benchmarks.csproj
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<NoWarn>$(NoWarn);CS1591</NoWarn>
<OutputType>Exe</OutputType>
<GenerateProgramFile>false</GenerateProgramFile>
<PlatformTarget>$([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture)</PlatformTarget>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<AssemblyOriginatorKeyFile>../../Autofac.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
<PreserveCompilationContext>true</PreserveCompilationContext>
<CodeAnalysisRuleSet>../../build/Test.ruleset</CodeAnalysisRuleSet>
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<IsPackable>false</IsPackable>
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
<ImplicitUsings>enable</ImplicitUsings>
<IsPackable>false</IsPackable>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
<PreserveCompilationContext>true</PreserveCompilationContext>
<UseProjectReference Condition="'$(UseProjectReference)' == ''">true</UseProjectReference>
</PropertyGroup>
<ItemGroup>
<Using Include="BenchmarkDotNet.Attributes" />
Expand All @@ -25,15 +26,18 @@
<None Remove="BenchmarkDotNet.Artifacts\**" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.15.6" />
<PackageReference Include="BenchmarkDotNet" Version="0.15.8" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.556">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ItemGroup Condition="'$(UseProjectReference)' == 'true'">
<ProjectReference Include="..\..\src\Autofac\Autofac.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(UseProjectReference)' != 'true' and '$(BaselinePackageVersion)' != ''">
<PackageReference Include="Autofac" Version="$(BaselinePackageVersion)" />
</ItemGroup>
<ItemGroup>
<AdditionalFiles Include="..\..\build\stylecop.json" Link="stylecop.json" />
</ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion bench/Autofac.Benchmarks/ChildScopeResolveBenchmark.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Autofac.Benchmarks;

public class ChildScopeResolveBenchmark
{
private IContainer _container;
private IContainer _container = default!;

[Benchmark]
public void Resolve()
Expand Down
9 changes: 6 additions & 3 deletions bench/Autofac.Benchmarks/Decorators/DecoratorBenchmarkBase.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
// Copyright (c) Autofac Project. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

using Microsoft.CodeAnalysis.CSharp.Syntax;

namespace Autofac.Benchmarks.Decorators;

public abstract class DecoratorBenchmarkBase<TCommandHandler>
where TCommandHandler : notnull
{
protected IContainer Container { get; set; }
protected IContainer Container { get; set; } = default!;

[Benchmark(Baseline = true)]
public virtual void Baseline()
Expand All @@ -25,7 +28,7 @@ public virtual void ResolveEnumerableT(int repetitions)
using (var scope = Container.BeginLifetimeScope())
{
var iteration = 0;
object item = null;
object? item = null;
while (iteration++ < repetitions)
{
item = scope.Resolve<IEnumerable<TCommandHandler>>();
Expand All @@ -43,7 +46,7 @@ public virtual void ResolveT(int repetitions)
using (var scope = Container.BeginLifetimeScope())
{
var iteration = 0;
object item = null;
object? item = null;
while (iteration++ < repetitions)
{
item = scope.Resolve<TCommandHandler>();
Expand Down
2 changes: 1 addition & 1 deletion bench/Autofac.Benchmarks/DeepGraphResolveBenchmark.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace Autofac.Benchmarks;
/// </summary>
public class DeepGraphResolveBenchmark
{
private IContainer _container;
private IContainer _container = default!;

[GlobalSetup]
public void Setup()
Expand Down
2 changes: 1 addition & 1 deletion bench/Autofac.Benchmarks/EnumerableResolveBenchmark.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Autofac.Benchmarks;

public class EnumerableResolveBenchmark
{
private IContainer _container;
private IContainer _container = default!;

[GlobalSetup]
public void Setup()
Expand Down
2 changes: 1 addition & 1 deletion bench/Autofac.Benchmarks/LambdaResolveBenchmark.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Autofac.Benchmarks;

public class LambdaResolveBenchmark
{
private IContainer _container;
private IContainer _container = default!;

[GlobalSetup]
public void Setup()
Expand Down
2 changes: 1 addition & 1 deletion bench/Autofac.Benchmarks/MultiConstructorBenchmark.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Autofac.Benchmarks;

public class MultiConstructorBenchmark
{
private IContainer _container;
private IContainer _container = default!;

[GlobalSetup]
public void Setup()
Expand Down
2 changes: 1 addition & 1 deletion bench/Autofac.Benchmarks/OpenGenericBenchmark.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Autofac.Benchmarks;

public class OpenGenericBenchmark
{
private IContainer _container;
private IContainer _container = default!;

[GlobalSetup]
public void Setup()
Expand Down
92 changes: 90 additions & 2 deletions bench/Autofac.Benchmarks/Program.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,100 @@
// Copyright (c) Autofac Project. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Running;

namespace Autofac.Benchmarks;

internal static class Program
{
internal static void Main(string[] args) =>
new BenchmarkSwitcher(BenchmarkSet.All).Run(args, new BenchmarkConfig());
internal static void Main(string[] args)
{
ArgumentNullException.ThrowIfNull(args);
var (filteredArgs, baselineVersion) = ExtractBaselineVersion(args);

// Usage:
//
// Just run the benchmark with the source code version of the project:
// dotnet run -c Release --project bench/Autofac.Benchmarks -- --filter *Benchmarks*
//
// Run the benchmark comparing the source code version to a specific package version:
// dotnet run -c Release --project bench/Autofac.Benchmarks -- --baseline-version 9.0.0 --filter *Benchmarks*
//
// Markdown tables are emitted by default; see BenchmarkDotNet.Artifacts/.../results/*.md.
var config = new BenchmarkConfig();

config.AddJob(
Job.Default
.WithId("Source"));

if (!string.IsNullOrWhiteSpace(baselineVersion))
{
config.AddJob(
Job.Default
.WithId($"Package-{baselineVersion}")
.AsBaseline()
.WithMsBuildArguments(
"/p:UseProjectReference=false",
$"/p:BaselinePackageVersion={baselineVersion}"));
}

Console.WriteLine($"Benchmark types configured: {BenchmarkSet.All.Length}");
new BenchmarkSwitcher(BenchmarkSet.All).Run(filteredArgs, config);
}

private static (string[] RemainingArgs, string? BaselineVersion) ExtractBaselineVersion(string[] args)
{
var forwarded = new List<string>(args.Length);
string? baseline = null;

for (var i = 0; i < args.Length; i++)
{
var arg = args[i];
if (TryMatchBaselineArg(arg, out var inlineVersion))
{
if (!string.IsNullOrWhiteSpace(inlineVersion))
{
baseline = inlineVersion;
continue;
}

if (i + 1 >= args.Length)
{
throw new ArgumentException("Missing version value for baseline argument.", nameof(args));
}

baseline = args[++i];
continue;
}

forwarded.Add(arg);
}

return (forwarded.ToArray(), baseline);
}

private static bool TryMatchBaselineArg(string arg, out string? valueFromAssignment)
{
valueFromAssignment = null;

static bool Matches(string candidate) =>
candidate.Equals("--baseline-version", StringComparison.OrdinalIgnoreCase) ||
candidate.Equals("--baselineVersion", StringComparison.OrdinalIgnoreCase);

var equalsIndex = arg.AsSpan().IndexOf('=');
if (equalsIndex >= 0)
{
var prefix = arg[..equalsIndex];
if (Matches(prefix))
{
valueFromAssignment = arg[(equalsIndex + 1)..];
return true;
}

return false;
}

return Matches(arg);
}
}
14 changes: 7 additions & 7 deletions bench/Autofac.Benchmarks/PropertyInjectionBenchmark.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Autofac.Benchmarks;

public class PropertyInjectionBenchmark
{
private IContainer _container;
private IContainer _container = default!;

[GlobalSetup]
public void Setup()
Expand All @@ -30,29 +30,29 @@ public void Resolve()

internal class A
{
public B1 B1 { get; set; }
public B1? B1 { get; set; }

public B2 B2 { get; set; }
public B2? B2 { get; set; }
}

internal class B1
{
public C1 C1 { get; set; }
public C1? C1 { get; set; }
}

internal class B2
{
public C2 C2 { get; set; }
public C2? C2 { get; set; }
}

internal class C1
{
public D1 D1 { get; set; }
public D1? D1 { get; set; }
}

internal class C2
{
public D2 D2 { get; set; }
public D2? D2 { get; set; }
}

internal class D1
Expand Down
2 changes: 1 addition & 1 deletion bench/Autofac.Benchmarks/RequiredPropertyBenchmark.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Autofac.Benchmarks;

public class RequiredPropertyBenchmark
{
private IContainer _container;
private IContainer _container = default!;

[GlobalSetup]
public void Setup()
Expand Down
2 changes: 1 addition & 1 deletion bench/Autofac.Benchmarks/RootContainerResolveBenchmark.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace Autofac.Benchmarks;
/// </summary>
public class RootContainerResolveBenchmark
{
private IContainer _container;
private IContainer _container = default!;

[GlobalSetup]
public void Setup()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the MIT License. See LICENSE in the project root for license information.

using System.Reflection;
using Autofac.Diagnostics;
using Autofac.Util;

namespace Autofac.Core.Activators.Reflection;
Expand Down Expand Up @@ -49,11 +50,18 @@ public static void InjectProperties(IComponentContext context, object instance,
}

var resolveParameters = parameters as Parameter[] ?? parameters.ToArray();
var recordMetrics = AutofacMetrics.MetricsEnabled;
ValueStopwatch instrumentationTimer = default;
if (recordMetrics)
{
instrumentationTimer = ValueStopwatch.StartNew();
}

var injectablePropertiesCache = ReflectionCacheSet.Shared.Internal.AutowiringInjectableProperties;

var instanceType = instance.GetType();
var injectableProperties = injectablePropertiesCache.GetOrAdd(instanceType, type => GetInjectableProperties(type).ToList());
var injectedProperties = 0;

for (var index = 0; index < injectableProperties.Count; index++)
{
Expand All @@ -77,6 +85,7 @@ public static void InjectProperties(IComponentContext context, object instance,
{
var setter = ReflectionCacheSet.Shared.Internal.AutowiringPropertySetters.GetOrAdd(property, MakeFastPropertySetter);
setter(instance, valueProvider!());
injectedProperties++;
continue;
}

Expand All @@ -86,8 +95,18 @@ public static void InjectProperties(IComponentContext context, object instance,
{
var setter = ReflectionCacheSet.Shared.Internal.AutowiringPropertySetters.GetOrAdd(property, MakeFastPropertySetter);
setter(instance, propertyValue);
injectedProperties++;
}
}

if (recordMetrics)
{
AutofacMetrics.RecordPropertyInjection(
instanceType,
injectableProperties.Count,
injectedProperties,
instrumentationTimer.GetElapsedTime());
}
}

private static IEnumerable<PropertyInfo> GetInjectableProperties(Type instanceType)
Expand Down
Loading