make superior
The last experiment The code was written in a rather random manner, but this time we have optimized it to the best of our knowledge.
But it still doesn't beat Dapper aot, even though it doesn't use the Interceptor, but theoretically its optimization shouldn't be that far off.
Knowledge gap quite a bit ah, can not understand Dapper aot utilize what posture lead, there are gods can teach?
optimal point
Reduced type judgment
Make type judgments in advance and use switch cases to reduce judgments during generation.
beforehand
var needConvert = typeof(string) != (i);
((d,r) => = (r,j,needConvert));
beyond
switch (name)
{
case "age":
(type == typeof(int) ? 1 : 2);
break;
switch (ss[j])
{
case 1:
= EntitiesGenerator.ReadToInt32Nullable(reader,j);
break;
case 2:
= EntitiesGenerator.ReadToInt32NullableConvert(reader,j);
break;
Avoid generating delegates
Remove the use of delegate generation
beforehand
var s = new List<Action<, IDataReader>>();
for (int i = 0; i < ; i++)
{
var j = i;
switch ((j).ToLower())
{
case "age":
{
// int?
var needConvert = typeof(int) != (i);
((d,r) => = DBExtensions.ReadToInt32Nullable(r,j,needConvert));
}
break;
case "name":
{
// string
var needConvert = typeof(string) != (i);
((d,r) => = (r,j,needConvert));
}
break;
case "weight":
{
// float?
var needConvert = typeof(float) != (i);
((d,r) => = (r,j,needConvert));
}
break;
default:
break;
}
}
while (())
{
var d = new ();
foreach (var item in s)
{
item?.Invoke(d,reader);
}
yield return d;
}
beyond
var s = new List<int>();
for (int i = 0; i < ; i++)
{
var name = (i).ToLower();
var type = (i);
switch (name)
{
case "age":
(type == typeof(int) ? 1 : 2);
break;
case "name":
(type == typeof(string) ? 3 : 4);
break;
case "weight":
(type == typeof(float) ? 5 : 6);
break;
default:
break;
}
}
ss = ();
var d = new ();
for (int j = 0; j < ; j++)
{
switch (ss[j])
{
case 1:
= EntitiesGenerator.ReadToInt32Nullable(reader,j);
break;
case 2:
= EntitiesGenerator.ReadToInt32NullableConvert(reader,j);
break;
case 3:
= (reader,j);
break;
case 4:
= (reader,j);
break;
case 5:
= (reader,j);
break;
case 6:
= (reader,j);
break;
default:
break;
}
}
Add reader field to determine caching
Add caching to reduce duplicate generation
var h = ();
if (!(h, out var ss))
{
var s = new List<int>();
for (int i = 0; i < ; i++)
in the end
BenchmarkDotNet v0.13.12, Windows 10 (10.0.19045.4651/22H2/2022Update)
Intel Core i7-10700 CPU 2.90GHz, 1 CPU, 16 logical and 8 physical cores
.NET SDK 9.0.100-preview.5.24307.3
[Host] : .NET 8.0.6 (8.0.624.26715), X64 RyuJIT AVX2
DefaultJob : .NET 8.0.6 (8.0.624.26715), X64 RyuJIT AVX2
Method | Categories | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Gen2 | Allocated | Alloc Ratio |
---|---|---|---|---|---|---|---|---|---|---|---|
SourceGeneratorMappingFirst | 1 | 434.7 ns | 8.67 ns | 7.69 ns | 0.84 | 0.02 | 0.0401 | 0.0396 | - | 336 B | 1.20 |
SetClassFirst | 1 | 516.8 ns | 9.86 ns | 10.55 ns | 1.00 | 0.00 | 0.0334 | 0.0324 | 0.0019 | 280 B | 1.00 |
DapperMappingFirst AOT | 1 | 1,333.4 ns | 2.49 ns | 2.33 ns | 2.58 | 0.06 | 0.0324 | - | - | 280 B | 1.00 |
DapperMappingFirst | 1 | 1,421.4 ns | 3.08 ns | 2.88 ns | 2.84 | 0.12 | 0.0496 | - | - | 416 B | 1.49 |
SetClass | 1000 | 8,139.8 ns | 130.22 ns | 115.43 ns | 1.00 | 0.00 | 6.7902 | 1.6937 | - | 56840 B | 1.00 |
DapperMapping AOT | 1000 | 16,373.8 ns | 275.34 ns | 244.08 ns | 2.01 | 0.05 | 6.7749 | 0.9460 | - | 56840 B | 1.00 |
SourceGeneratorMapping | 1000 | 20,911.5 ns | 77.69 ns | 60.65 ns | 2.57 | 0.04 | 6.7749 | 1.6785 | - | 56896 B | 1.00 |
DapperMapping | 1000 | 48,707.3 ns | 430.05 ns | 381.23 ns | 5.67 | 0.29 | 12.5122 | 2.0752 | - | 105120 B | 1.85 |