写点什么

SourceGenerator 生成 db to class 代码优化结果记录

作者:八苦-瞿昙
  • 2024-10-18
    中国台湾
  • 本文字数:1872 字

    阅读完需:约 6 分钟

优化

上一次实验 代码写的较为随意,本次穷尽所学,优化了一把,


不过果然还是没 比过 Dapper aot, 虽然没使用 Interceptor, 但理论上其优化不该有这么大差距


知识差距不少呀,都看不懂 Dapper aot 利用了什么姿势领先, 有大神们能教教吗?

优化点

减少类型判断

提前 做类型判断,并在生成时利用 switch case 减少判断


之前


 var needConvert = typeof(string) != reader.GetFieldType(i);s.Add((d,r) => d.Name = DBExtensions.ReadToString(r,j,needConvert));
复制代码


之后


     switch (name)    {            case "age":        s.Add(type == typeof(int) ? 1 : 2);         break;

switch (ss[j]) { case 1: d.Age = EntitiesGenerator.ReadToInt32Nullable(reader,j); break; case 2: d.Age = EntitiesGenerator.ReadToInt32NullableConvert(reader,j); break;
复制代码

避免生成委托

去除委托生成使用


之前


var s = new List<Action<BenchmarkTest.Dog, IDataReader>>(reader.FieldCount);for (int i = 0; i < reader.FieldCount; i++){    var j = i;    switch (reader.GetName(j).ToLower())    {                case "age":         {            // int?                        var needConvert = typeof(int) != reader.GetFieldType(i);            s.Add((d,r) => d.Age = DBExtensions.ReadToInt32Nullable(r,j,needConvert));                     }        break;        case "name":         {            // string                        var needConvert = typeof(string) != reader.GetFieldType(i);            s.Add((d,r) => d.Name = DBExtensions.ReadToString(r,j,needConvert));                     }        break;        case "weight":         {            // float?                        var needConvert = typeof(float) != reader.GetFieldType(i);            s.Add((d,r) => d.Weight = DBExtensions.ReadToFloatNullable(r,j,needConvert));                     }        break;        default:            break;    }}while (reader.Read()){    var d = new BenchmarkTest.Dog();    foreach (var item in s)    {        item?.Invoke(d,reader);    }    yield return d;}
复制代码


之后


var s = new List<int>(reader.FieldCount);for (int i = 0; i < reader.FieldCount; i++){    var name = reader.GetName(i).ToLower();    var type = reader.GetFieldType(i);    switch (name)    {            case "age":        s.Add(type == typeof(int) ? 1 : 2);         break;
case "name": s.Add(type == typeof(string) ? 3 : 4); break;
case "weight": s.Add(type == typeof(float) ? 5 : 6); break;
default: break; }}ss = s.ToArray();
var d = new BenchmarkTest.Dog();for (int j = 0; j < ss.Length; j++){ switch (ss[j]) { case 1: d.Age = EntitiesGenerator.ReadToInt32Nullable(reader,j); break; case 2: d.Age = EntitiesGenerator.ReadToInt32NullableConvert(reader,j); break;
case 3: d.Name = EntitiesGenerator.ReadToString(reader,j); break; case 4: d.Name = EntitiesGenerator.ReadToStringConvert(reader,j); break;
case 5: d.Weight = EntitiesGenerator.ReadToFloatNullable(reader,j); break; case 6: d.Weight = EntitiesGenerator.ReadToFloatNullableConvert(reader,j); break;
default: break; }}
复制代码

添加 reader 字段判断缓存

添加缓存,减少重复生成


   var h = reader.GetColumnHash();   if (!tokenCache.TryGetValue(h, out var ss))   {       var s = new List<int>(reader.FieldCount);       for (int i = 0; i < reader.FieldCount; i++)
复制代码

结果


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
复制代码



发布于: 刚刚阅读数: 4
用户头像

八苦-瞿昙

关注

一个假和尚,不懂人情世故。 2018-11-23 加入

会点点技术,能写些代码,只爱静静。 g hub: https://github.com/fs7744 黑历史:https://www.cnblogs.com/fs7744

评论

发布
暂无评论
SourceGenerator 生成db to class代码优化结果记录_dotnet_八苦-瞿昙_InfoQ写作社区