Skip to content

Commit

Permalink
More optimizations and cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
mikernet committed Feb 9, 2024
1 parent 1eed97a commit 0837d0c
Show file tree
Hide file tree
Showing 5 changed files with 319 additions and 198 deletions.
174 changes: 98 additions & 76 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,158 +29,180 @@ You can view the API on [FuGet](https://www.fuget.org/packages/Singulink.Reflect

## Benchmarks

**.NET 8**
```
Entries that end in `_Activator` use `System.Activator` and the entries below that ending in `_ObjectFactory` use this library for comparison.

### .NET 8

#### Reference Types

| Method | Mean | Error | StdDev | Gen0 | Allocated |
|----------------------------------------- |------------:|----------:|----------:|-------:|----------:|
| Activator_Object | 14.9644 ns | 0.2901 ns | 0.3341 ns | 0.0057 | 24 B |
| ObjectFactory_Object | 6.5780 ns | 0.0587 ns | 0.0549 ns | 0.0057 | 24 B |
| ObjectFactory_Object_Delegate | 6.3640 ns | 0.0508 ns | 0.0451 ns | 0.0057 | 24 B |
|----------------------------------------- |------------:|----------:|----------:|-------:|----------:|
| Activator_ObjectPrivateCtor | 11.9688 ns | 0.0894 ns | 0.0793 ns | 0.0057 | 24 B |
| ObjectFactory_ObjectPrivateCtor | 6.6406 ns | 0.0857 ns | 0.0760 ns | 0.0057 | 24 B |
| ObjectFactory_ObjectPrivateCtor_Delegate | 6.3639 ns | 0.0569 ns | 0.0532 ns | 0.0057 | 24 B |
|----------------------------------------- |------------:|----------:|----------:|-------:|----------:|
| Activator_ObjectWithParam | 285.5964 ns | 2.1783 ns | 1.9310 ns | 0.0858 | 360 B |
| ObjectFactory_ObjectWithParam_Delegate | 6.5055 ns | 0.1480 ns | 0.1384 ns | 0.0057 | 24 B |
|----------------------------------------- |------------:|----------:|----------:|-------:|----------:|
| Activator_Struct | 0.1714 ns | 0.0382 ns | 0.0357 ns | - | - |
| ObjectFactory_Struct | 0.1339 ns | 0.0159 ns | 0.0149 ns | - | - |
| ObjectFactory_Struct_Delegate | 0.4148 ns | 0.0089 ns | 0.0070 ns | - | - |
|----------------------------------------- |------------:|----------:|----------:|-------:|----------:|
| Activator_StructWithParams | 277.3095 ns | 1.3876 ns | 1.2300 ns | 0.0858 | 360 B |
| ObjectFactory_StructWithParams_Delegate | 1.7756 ns | 0.0062 ns | 0.0051 ns | - | - |
```
| Object_Activator | 14.0557 ns | 0.3502 ns | 0.4429 ns | 0.0057 | 24 B |
| Object_ObjectFactory | 6.4743 ns | 0.0699 ns | 0.0653 ns | 0.0057 | 24 B |
| Object_ObjectFactory_Delegate | 6.2483 ns | 0.1278 ns | 0.1067 ns | 0.0057 | 24 B |
| ---
| ObjectPrivateCtor_Activator | 12.3806 ns | 0.1191 ns | 0.1114 ns | 0.0057 | 24 B |
| ObjectPrivateCtor_ObjectFactory | 6.5123 ns | 0.1423 ns | 0.1261 ns | 0.0057 | 24 B |
| ObjectPrivateCtor_ObjectFactory_Delegate | 6.2050 ns | 0.1144 ns | 0.1070 ns | 0.0057 | 24 B |
| ---
| ObjectWithParam_Activator | 290.2104 ns | 2.2835 ns | 2.0242 ns | 0.0858 | 360 B |
| ObjectWithParam_ObjectFactory_Delegate | 6.1892 ns | 0.0906 ns | 0.0707 ns | 0.0057 | 24 B |

#### Value Types

**.NET 8 Native AOT**
```
| Method | Mean | Error | StdDev | Gen0 | Allocated |
|----------------------------------------- |------------:|----------:|----------:|-------:|----------:|
| Activator_Object | 5.8690 ns | 0.1876 ns | 0.2920 ns | 0.0057 | 24 B |
| ObjectFactory_Object | 5.4405 ns | 0.1007 ns | 0.0942 ns | 0.0057 | 24 B |
| ObjectFactory_Object_Delegate | 5.8968 ns | 0.0417 ns | 0.0390 ns | 0.0057 | 24 B |
|----------------------------------------- |------------:|----------:|----------:|-------:|----------:|
| Activator_ObjectPrivateCtor | 93.0655 ns | 0.7956 ns | 0.7052 ns | 0.0057 | 24 B |
| ObjectFactory_ObjectPrivateCtor | 77.0504 ns | 0.6919 ns | 0.6134 ns | 0.0324 | 136 B |
| ObjectFactory_ObjectPrivateCtor_Delegate | 76.3781 ns | 0.9018 ns | 0.8435 ns | 0.0324 | 136 B |
|----------------------------------------- |------------:|----------:|----------:|-------:|----------:|
| Activator_ObjectWithParam | 365.1306 ns | 2.5832 ns | 2.4163 ns | 0.0763 | 320 B |
| ObjectFactory_ObjectWithParam_Delegate | 125.5081 ns | 1.9267 ns | 1.8022 ns | 0.0496 | 208 B |
| Struct_Activator | 0.1334 ns | 0.0067 ns | 0.0056 ns | - | - |
| Struct_ObjectFactory | 0.1406 ns | 0.0072 ns | 0.0063 ns | - | - |
| Struct_ObjectFactory_Delegate | 0.1395 ns | 0.0121 ns | 0.0107 ns | - | - |
| ---
| StructWithParams_Activator | 292.7251 ns | 3.2207 ns | 3.0127 ns | 0.0858 | 360 B |
| StructWithParams_ObjectFactory_Delegate | 1.7616 ns | 0.0289 ns | 0.0270 ns | - | - |

### .NET 8 Native AOT

#### Reference Types

| Method | Mean | Error | StdDev | Gen0 | Allocated |
|----------------------------------------- |------------:|----------:|----------:|-------:|----------:|
| Activator_Struct | 0.1400 ns | 0.0131 ns | 0.0116 ns | - | - |
| ObjectFactory_Struct | 0.1355 ns | 0.0073 ns | 0.0061 ns | - | - |
| ObjectFactory_Struct_Delegate | 1.7573 ns | 0.0323 ns | 0.0302 ns | - | - |
| Object_Activator | 5.5204 ns | 0.1827 ns | 0.2561 ns | 0.0057 | 24 B |
| Object_ObjectFactory | 5.4420 ns | 0.0637 ns | 0.0532 ns | 0.0057 | 24 B |
| Object_ObjectFactory_Delegate | 5.6431 ns | 0.1214 ns | 0.1135 ns | 0.0057 | 24 B |
| ---
| ObjectPrivateCtor_Activator | 91.9347 ns | 1.0674 ns | 0.8913 ns | 0.0057 | 24 B |
| ObjectPrivateCtor_ObjectFactory | 24.5102 ns | 0.0418 ns | 0.0349 ns | 0.0057 | 24 B |
| ObjectPrivateCtor_ObjectFactory_Delegate | 24.0892 ns | 0.2957 ns | 0.2766 ns | 0.0057 | 24 B |
| ---
| ObjectWithParam_Activator | 337.3210 ns | 1.9566 ns | 1.6339 ns | 0.0763 | 320 B |
| ObjectWithParam_ObjectFactory_Delegate | 32.2363 ns | 0.2639 ns | 0.2339 ns | 0.0057 | 24 B |

#### Value Types

| Method | Mean | Error | StdDev | Gen0 | Allocated |
|----------------------------------------- |------------:|----------:|----------:|-------:|----------:|
| Activator_StructWithParams | 344.7916 ns | 6.7640 ns | 7.5182 ns | 0.0935 | 392 B |
| ObjectFactory_StructWithParams_Delegate | 193.1942 ns | 1.5188 ns | 1.4207 ns | 0.0706 | 296 B |
```
| Struct_Activator | 0.1423 ns | 0.0129 ns | 0.0121 ns | - | - |
| Struct_ObjectFactory | 0.1334 ns | 0.0060 ns | 0.0056 ns | - | - |
| Struct_ObjectFactory_Delegate | 0.2120 ns | 0.0297 ns | 0.0330 ns | - | - |
| ---
| StructWithParams_Activator | 317.8065 ns | 1.0806 ns | 0.8437 ns | 0.0935 | 392 B |
| StructWithParams_ObjectFactory_Delegate | 48.9843 ns | 0.7990 ns | 0.7474 ns | 0.0191 | 80 B |

### .NET Framework 4.8

#### Reference Types

**.NET Framework**
```
| Method | Mean | Error | StdDev | Gen0 | Allocated |
|----------------------------------------- |-------------:|-----------:|-----------:|-------:|----------:|
| Activator_Object | 72.919 ns | 1.5117 ns | 2.8762 ns | 0.0057 | 24 B |
| ObjectFactory_Object | 12.983 ns | 0.2200 ns | 0.1837 ns | 0.0057 | 24 B |
| ObjectFactory_Object_Delegate | 12.500 ns | 0.1472 ns | 0.1229 ns | 0.0057 | 24 B |
|----------------------------------------- |-------------:|-----------:|-----------:|-------:|----------:|
| Activator_ObjectPrivateCtor | 57.444 ns | 1.0517 ns | 1.8420 ns | 0.0057 | 24 B |
| ObjectFactory_ObjectPrivateCtor | 13.601 ns | 0.3442 ns | 0.5152 ns | 0.0057 | 24 B |
| ObjectFactory_ObjectPrivateCtor_Delegate | 12.489 ns | 0.1248 ns | 0.0975 ns | 0.0057 | 24 B |
|----------------------------------------- |-------------:|-----------:|-----------:|-------:|----------:|
| Activator_ObjectWithParam | 966.560 ns | 9.5869 ns | 8.0055 ns | 0.1030 | 433 B |
| ObjectFactory_ObjectWithParam_Delegate | 11.007 ns | 0.1479 ns | 0.1311 ns | 0.0057 | 24 B |
|----------------------------------------- |-------------:|-----------:|-----------:|-------:|----------:|
| Activator_Struct | 54.208 ns | 0.6618 ns | 0.5867 ns | 0.0076 | 32 B |
| ObjectFactory_Struct | 4.110 ns | 0.1152 ns | 0.1233 ns | - | - |
| ObjectFactory_Struct_Delegate | 3.207 ns | 0.0541 ns | 0.0506 ns | - | - |
| Object_Activator | 64.296 ns | 0.5001 ns | 0.4176 ns | 0.0057 | 24 B |
| Object_ObjectFactory | 17.374 ns | 0.1401 ns | 0.1090 ns | 0.0057 | 24 B |
| Object_ObjectFactory_Delegate | 11.589 ns | 0.2366 ns | 0.2097 ns | 0.0057 | 24 B |
| ---
| ObjectPrivateCtor_Activator | 57.444 ns | 1.0517 ns | 1.8420 ns | 0.0057 | 24 B |
| Object_ObjectFactoryPrivateCtor | 15.704 ns | 0.2986 ns | 0.2499 ns | 0.0057 | 24 B |
| Object_ObjectFactoryPrivateCtor_Delegate | 11.608 ns | 0.2255 ns | 0.2110 ns | 0.0057 | 24 B |
| ---
| ObjectWithParam_Activator | 898.057 ns | 6.3406 ns | 4.9503 ns | 0.1030 | 433 B |
| ObjectWithParam_ObjectFactory_Delegate | 9.940 ns | 0.0301 ns | 0.0267 ns | 0.0057 | 24 B |

#### Value Types

| Method | Mean | Error | StdDev | Gen0 | Allocated |
|----------------------------------------- |-------------:|-----------:|-----------:|-------:|----------:|
| Activator_StructWithParams | 1,124.746 ns | 15.8511 ns | 13.2364 ns | 0.1202 | 505 B |
| ObjectFactory_StructWithParams_Delegate | 8.977 ns | 0.1744 ns | 0.1362 ns | - | - |
```
| Struct_Activator | 49.163 ns | 0.3674 ns | 0.3437 ns | 0.0076 | 32 B |
| Struct_ObjectFactory | 3.894 ns | 0.0265 ns | 0.0235 ns | - | - |
| Struct_ObjectFactory_Delegate | 3.069 ns | 0.0138 ns | 0.0123 ns | - | - |
| ---
| StructWithParams_Activator | 1,116.467 ns | 4.2834 ns | 4.0067 ns | 0.1202 | 505 B |
| StructWithParams_ObjectFactory_Delegate | 8.235 ns | 0.0357 ns | 0.0279 ns | - | - |

This is the benchmark code used to generate the above results:
### Benchmark Code

```cs
private readonly DefaultActivator<SomeObject> _objectFactory = ObjectFactory.GetActivator<SomeObject>();
private readonly DefaultActivator<SomeObjectPrivateCtor> _objectFactoryPrivateCtor = ObjectFactory.GetActivator<SomeObjectPrivateCtor>(true);
private readonly Func<string, SomeObject> _objectFactoryWithParam = ObjectFactory.GetActivator<string, SomeObject>();
private readonly DefaultActivator<SomeStruct> _structFactory = ObjectFactory.GetActivator<SomeStruct>();
private readonly Func<long, long, SomeStruct> _structFactoryWithParams = ObjectFactory.GetActivator<long, long, SomeStruct>();
private readonly DefaultActivator<SomeObject> _objectFactory =
ObjectFactory.GetActivator<SomeObject>();
private readonly DefaultActivator<SomeObjectPrivateCtor> _objectFactoryPrivateCtor =
ObjectFactory.GetActivator<SomeObjectPrivateCtor>(true);
private readonly Func<string, SomeObject> _objectFactoryWithParam =
ObjectFactory.GetActivator<string, SomeObject>();
private readonly DefaultActivator<SomeStruct> _structFactory =
ObjectFactory.GetActivator<SomeStruct>();
private readonly Func<long, long, SomeStruct> _structFactoryWithParams =
ObjectFactory.GetActivator<long, long, SomeStruct>();

[Benchmark]
public SomeObject Activator_Object()
public SomeObject Object_Activator()
{
return Activator.CreateInstance<SomeObject>();
}

[Benchmark]
public SomeObject ObjectFactory_Object()
public SomeObject Object_ObjectFactory()
{
return ObjectFactory.CreateInstance<SomeObject>();
}

[Benchmark]
public SomeObject ObjectFactory_Object_Delegate()
public SomeObject Object_ObjectFactory_Delegate()
{
return _objectFactory.Invoke();
}

[Benchmark]
public SomeObjectPrivateCtor Activator_ObjectPrivateCtor()
public SomeObjectPrivateCtor ObjectPrivateCtor_Activator()
{
return (SomeObjectPrivateCtor)Activator.CreateInstance(typeof(SomeObjectPrivateCtor), true)!;
}

[Benchmark]
public SomeObjectPrivateCtor ObjectFactory_ObjectPrivateCtor()
public SomeObjectPrivateCtor ObjectPrivateCtor_ObjectFactory()
{
return ObjectFactory.CreateInstance<SomeObjectPrivateCtor>(true);
}

[Benchmark]
public SomeObjectPrivateCtor ObjectFactory_ObjectPrivateCtor_Delegate()
public SomeObjectPrivateCtor ObjectPrivateCtor_ObjectFactory_Delegate()
{
return _objectFactoryPrivateCtor.Invoke();
}

[Benchmark]
public SomeObject Activator_ObjectWithParam()
public SomeObject ObjectWithParam_Activator()
{
return (SomeObject)Activator.CreateInstance(typeof(SomeObject), "test")!;
}

[Benchmark]
public SomeObject ObjectFactory_ObjectWithParam_Delegate()
public SomeObject ObjectWithParam_ObjectFactory_Delegate()
{
return _objectFactoryWithParam.Invoke("test");
}

[Benchmark]
public SomeStruct Activator_Struct()
public SomeStruct Struct_Activator()
{
return Activator.CreateInstance<SomeStruct>();
}

[Benchmark]
public SomeStruct ObjectFactory_Struct()
public SomeStruct Struct_ObjectFactory()
{
return ObjectFactory.CreateInstance<SomeStruct>();
}

[Benchmark]
public SomeStruct ObjectFactory_Struct_Delegate()
public SomeStruct Struct_ObjectFactory_Delegate()
{
return _structFactory.Invoke();
}

[Benchmark]
public SomeStruct Activator_StructWithParams()
public SomeStruct StructWithParams_Activator()
{
return (SomeStruct)Activator.CreateInstance(typeof(SomeStruct), 1L, 2L)!;
}

[Benchmark]
public SomeStruct ObjectFactory_StructWithParams_Delegate()
public SomeStruct StructWithParams_ObjectFactory_Delegate()
{
return _structFactoryWithParams.Invoke(1, 2);
}
Expand Down
30 changes: 15 additions & 15 deletions Source/Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
<Project>
<PropertyGroup>
<LangVersion>12.0</LangVersion>
<Nullable>enable</Nullable>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PropertyGroup>
<LangVersion>12.0</LangVersion>
<Nullable>enable</Nullable>
<GenerateDocumentationFile>true</GenerateDocumentationFile>

<WeaverConfiguration>
<Weavers>
<RuntimeNullables />
</Weavers>
</WeaverConfiguration>
</PropertyGroup>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>

<ItemGroup>
<!-- Fody -->
<ItemGroup>
<!-- Fody -->
<PackageReference Include="Fody" Version="6.8.0" PrivateAssets="all" />
<PackageReference Include="RuntimeNullables.Fody" Version="1.0.5" PrivateAssets="all" />

<!-- Analyzers -->
<PackageReference Include="DotNetAnalyzers.DocumentationAnalyzers" Version="1.0.0-beta.59" PrivateAssets="all" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="all" />
<PackageReference Include="Roslynator.Analyzers" Version="4.4.0" PrivateAssets="all" />
</ItemGroup>
<!-- Analyzers -->
<PackageReference Include="DotNetAnalyzers.DocumentationAnalyzers" Version="1.0.0-beta.59" PrivateAssets="all" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="all" />
<PackageReference Include="Roslynator.Analyzers" Version="4.4.0" PrivateAssets="all" />
</ItemGroup>
</Project>
Loading

0 comments on commit 0837d0c

Please sign in to comment.