首页 星云 工具 资源 星选 资讯 热门工具
:

PDF转图片 完全免费 小红书视频下载 无水印 抖音视频下载 无水印 数字星空

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

编程知识
2024年08月02日 09:58

优化

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

不过果然还是没 比过 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


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
From:https://www.cnblogs.com/fs7744/p/18338301
本文地址: http://shuzixingkong.net/article/692
0评论
提交 加载更多评论
其他文章 Netty的源码分析和业务场景
Netty 是一个高性能、异步事件驱动的网络应用框架,它基于 Java NIO 构建,广泛应用于互联网、大数据、游戏开发、通信行业等多个领域。以下是对 Netty 的源码分析、业务场景的详细介绍: 源码概述 Netty 的核心组件:Netty 的架构设计围绕着事件驱动的核心思想,主要包括 Chann
.NET8 Blazor 从入门到精通:(一)关键概念
目录Blazor 的关键概念项目模板Razor 语法依赖注入注入配置HeadOutlet 组件@code 分离Blazor 调试CSS 隔离调用JavaScript 最近在学习 Blazor ,在B站上找了一个国外的课程边看边学习。嗯,原价¥1503的课程,大概200多美元,课程链接如下: B站(大
.NET8 Blazor 从入门到精通:(一)关键概念 .NET8 Blazor 从入门到精通:(一)关键概念 .NET8 Blazor 从入门到精通:(一)关键概念
浅析前端数据埋点监控:用户行为与性能分析的桥梁
总的来说,前端埋点技术不仅是提升用户体验和产品运行效率的利器,更是实现数据驱动决策的重要工具。随着各类专业工具的出现,如腾讯有数、百度统计和微软Clarity,企业可以根据需求选择最适合的工具进行数据分析和优化,从而在竞争激烈的市场中保持领先地位。通过深入理解用户行为和性能数据,企业能够做出更明智的
浅析前端数据埋点监控:用户行为与性能分析的桥梁 浅析前端数据埋点监控:用户行为与性能分析的桥梁 浅析前端数据埋点监控:用户行为与性能分析的桥梁
数据库系列: 主流分库分表中间件介绍(图文总结)
相关文章 数据库系列:MySQL慢查询分析和性能优化 数据库系列:MySQL索引优化总结(综合版) 数据库系列:高并发下的数据字段变更 数据库系列:覆盖索引和规避回表 数据库系列:数据库高可用及无损扩容 数据库系列:使用高区分度索引列提升性能 数据库系列:前缀索引和索引长度的取舍 数据库系列:MyS
数据库系列: 主流分库分表中间件介绍(图文总结) 数据库系列: 主流分库分表中间件介绍(图文总结)
Megacity Unity Demo工程学习
1.前言 Megacity Demo发布于2019年春,本博文撰写于2024年,ECS也早已Release并发布了1.2.3版本。 不过好在核心变化不大,多数接口也只是换了调用名称, 该Demo相较于之前的Book of the Dead(2018年发布),体量要小一些,主要演示DOTS相关内容。
Megacity Unity Demo工程学习 Megacity Unity Demo工程学习 Megacity Unity Demo工程学习
不止于面向对象的SOLID原则
SOLID原则是由人称”鲍勃大叔“的Rober C. Martin所提出来的。他用五个面向对象设计原则的首字母组成了SOLID,并使其得到了广泛传播。这五个原则罗列如下: 单一指责原则(Single Responsibility Principle):类的职责应该是单一的。所谓单一,是从变化的维度衡
不止于面向对象的SOLID原则 不止于面向对象的SOLID原则 不止于面向对象的SOLID原则
CSS mask-image 实现边缘淡出过渡效果
使用场景 在生产环境中,遇到一个需求,需要在一个深色风格的大屏页面中,嵌入 Google Maps。为了减少违和感,希望地图四边能够淡出过渡。 这里的“淡出过渡”,关键是淡出,而非降低透明度。 基于 Google Maps 的深色示例中,附加上述需求,效果如下: 简单的说,就是中间放地图,四周放标题
CSS mask-image 实现边缘淡出过渡效果 CSS mask-image 实现边缘淡出过渡效果 CSS mask-image 实现边缘淡出过渡效果
《最新出炉》系列初窥篇-Python+Playwright自动化测试-62 - 判断元素是否可操作
1.简介 有些页面元素的生命周期如同流星一闪,昙花一现。我们也不知道这个元素在没在页面中出现过,为了捕获这一美好瞬间,让其成为永恒。我们就来判断元素是否显示出现过。 在操作元素之前,可以先判断元素的状态。判断元素操作状态也可以用于断言。 2.常用的元素判断方法 2.1page对象调用的判断方法 pa
《最新出炉》系列初窥篇-Python+Playwright自动化测试-62 - 判断元素是否可操作 《最新出炉》系列初窥篇-Python+Playwright自动化测试-62 - 判断元素是否可操作 《最新出炉》系列初窥篇-Python+Playwright自动化测试-62 - 判断元素是否可操作