好奇

SourceGenerator 出现开始,好几年了,虽然一直好奇用SourceGenerator 生成代码 与 emit 等动态生成的代码会有多少差距,

但是一直特别懒,不想搞

其实 dapper aot 项目做了类似事情,不过功能特别积极,还引用了实验特性,所以还是想更为简单客观对比

本次乘着自己暂时性不懒了,做了一个基于 SourceGenerator 生成 从 dbReader转换为 class 数据的测试

no generate code when

  • Generic Type (如果不用 emit 动态生成,还真无法处理未知类型 T)
  • Anonymous Type (SourceGenerator 生成时机要早于匿名类生成,所以还没机会生成)

generate code

具体怎么做的就这里不写了,感兴趣参考 https://github.com/fs7744/SlowestEM

生成的代码带有一定 db结果动态类型处理,以此更接近实际使用


// <auto-generated/>
#pragma warning disable 8019 //disable 'unnecessary using directive' warning
using System;
using System.Data;
using System.Runtime.CompilerServices;
using System.Collections.Generic; namespace SlowestEM.Generator
{
public static partial class Dog_Accessors
{
public static IEnumerable<BenchmarkTest.Dog> Read(IDataReader reader)
{
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;
}
}
}
}

测试结果

mock db, 避免 db层实现性能和没有正确处理数据类型装箱拆箱问题

[Benchmark(Baseline = true), BenchmarkCategory("1")]
public void SetClassFirst()
{
Dog dog;
try
{
connection.Open();
var cmd = connection.CreateCommand();
cmd.CommandText = "select ";
using (var reader = cmd.ExecuteReader(CommandBehavior.Default))
{
if (reader.Read())
{
dog = new Dog();
dog.Name = reader.GetString(0);
dog.Age = reader.GetInt32(1);
dog.Weight = reader.GetFloat(2);
}
}
}
finally
{
connection.Close();
}
} [Benchmark, BenchmarkCategory("1")]
public void DapperMappingFirst()
{
var dogs = connection.QueryFirst<Dog>("select ");
} [Benchmark, BenchmarkCategory("1")]
public void SourceGeneratorMappingFirst()
{
Dog dog;
try
{
connection.Open();
var cmd = connection.CreateCommand();
cmd.CommandText = "select ";
using (var reader = cmd.ExecuteReader(CommandBehavior.Default))
{
dog = reader.ReadTo<Dog>().FirstOrDefault();
}
}
finally
{
connection.Close();
}
}

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 Allocated Alloc Ratio
SetClassFirst 1 实体 18.38 ns 0.378 ns 0.316 ns 1.00 0.00 0.0181 - 152 B 1.00
SourceGeneratorMappingFirst 1 实体 183.31 ns 3.525 ns 3.462 ns 9.98 0.14 0.0899 - 752 B 4.95
DapperMappingFirst 1 实体 1,336.69 ns 5.777 ns 5.121 ns 72.77 1.30 0.0343 - 288 B 1.89
SetClass 1000 实体 7,700.08 ns 87.311 ns 68.167 ns 1.00 0.00 6.7749 1.1139 56712 B 1.00
SourceGeneratorMapping 1000 实体 23,428.85 ns 262.698 ns 232.875 ns 3.04 0.03 6.8359 1.1292 57312 B 1.01
DapperMapping 1000 实体 48,880.92 ns 682.693 ns 533.002 ns 6.35 0.06 13.4888 2.1362 113048 B 1.99

一个基于 SourceGenerator 生成 从 dbReader转换为 class 数据的性能测试实验的更多相关文章

  1. 一个基于图的数据管理系统-gStore

    gStore是遵循 BSD协议的一个开源项目.一个基于图的 RDF 三元组存储的数据管理系统.该项目是北京大学.滑铁卢大学.香港科技大学的联合研究项目.中国北京大学计算机科学与技术研究所的数据库组对该 ...

  2. 基于Thinkphp5+phpQuery 网络爬虫抓取数据接口,统一输出接口数据api

    TP5_Splider 一个基于Thinkphp5+phpQuery 网络爬虫抓取数据接口 统一输出接口数据api.适合正在学习Vue,AngularJs框架学习 开发demo,需要接口并保证接口不跨 ...

  3. 一个基于原生JavaScript开发的、轻量的验证码生成插件

    Vcode.js 一个基于原生JavaScript开发的.轻量的验证码生成插件 V: 1.0.0 DEMO:https://jofunliang.github.io/Vcode.js/example. ...

  4. 一个基于.NET平台的自动化/压力测试系统设计简述

    AutoTest系统设计概述 AutoTest是一个基于.NET平台实现的自动化/压力测试的系统,可独立运行于windows平台下,支持分布式部署,不需要其他配置或编译器的支持.(本质是一个基于协议的 ...

  5. 构建一个基于 Spring 的 RESTful Web Service

    本文详细介绍了基于Spring创建一个“hello world” RESTful web service工程的步骤. 目标 构建一个service,接收如下HTTP GET请求: http://loc ...

  6. TensorFlow练习7: 基于RNN生成古诗词

      http://blog.topspeedsnail.com/archives/10542 主题 TensorFlow RNN不像传统的神经网络-它们的输出输出是固定的,而RNN允许我们输入输出向量 ...

  7. RSuite 一个基于 React.js 的 Web 组件库

    RSuite http://rsuite.github.io RSuite 是一个基于 React.js 开发的 Web 组件库,参考 Bootstrap 设计,提供其中常用组件,支持响应式布局. 我 ...

  8. Linux下c基于openssl生成MD5的函数

    Linux下openssl提供了一系列哈希及加密的函数,如果调用openssl提供的MD5函数生成任意字符串的MD5呢?下面提供了一段代码实现Linux下c字符串生成md5的函数. 具体代码: 1 2 ...

  9. 一个基于nodejs,支持http/https的中间人(MITM)代理,便于渗透测试和开发调试。

    源码地址:https://github.com/wuchangming/node-mitmproxy node-mitmproxy node-mitmproxy是一个基于nodejs,支持http/h ...

  10. 一个基于ES6+webpack的vue小demo

    上一篇文章<一个基于ES5的vue小demo>我们讲了如何用ES5,vue-router做一个小demo,接下来我们来把它变成基于ES6+webpack的demo. 一.环境搭建及代码转换 ...

随机推荐

  1. Visual Studio编程效率提升技巧集(提高.NET编程效率)

    前言 本文大姚将为你介绍一些Visual Studio的使用技巧和建议,旨在帮助.NET开发者更加高效地利用Visual Studio进行编程工作.无论你是.NET初学者还是经验丰富的.NET开发者, ...

  2. Linu部署服务启停脚本

    Linux项目部署启停 WEB应用(WAR包)部署 实际开发中,难免遇见新业务项目构建.项目重构(重新优化整个项目的架构,相当于重写),也可能是项目拆分多个模块,也可能部分拆分,但项目的模块化分离,就 ...

  3. Vue3等比例缩放图片组件

    本文由 ChatMoney团队出品 有些情况我们需要在各种刁钻的情况下都要保持图片比例不变,比如用户缩放窗口等改变布局的情况.实现原理就是通过容器的宽度和内边距在保持你想要的比例. 以下是基础功能的组 ...

  4. linux系统下,安装mysql教程

    1.查看mysql是否安装 首先我们需要查看软件是否已经安装,或者说查看安装的软件包名称.如查找是否安装mysql rpm -qa | grep mysql 2.卸载查到的软件 rpm -e --no ...

  5. 3代 I3 3220 对比12代 G6900 测试 入手 上手 评测

    3代 I3 3220 对比12代 G6900 测试 入手 上手 评测 I3 3220 的CPU-Z ,和cinebench r23 跑分. G6900 的CPU-Z ,和cinebench r23 跑 ...

  6. C# .NET Unix 时间戳

    10 位时间戳: public static long GetTimeStampTen() { return (DateTime.Now.ToUniversalTime().Ticks - 62135 ...

  7. Flashcat与出行科技企业一起实践多云可观测

    当前架构 某出行科技企业从单个公有云往多云转型,依托于国内领先的公有云提供商,采用多云架构,在可用性.弹性.成本.供应商依赖方面,拥有了显著的优势. 相应的,多云架构也给技术团队带来了一定的复杂度和技 ...

  8. redis 锁

    demo1 public ErrorCode initDemo1(@RequestParam("orderNo") String orderNo) throws IOExcepti ...

  9. Windows CSC提权漏洞复现(CVE-2024-26229)

    漏洞信息 Windows CSC服务特权提升漏洞. 当程序向缓冲区写入的数据超出其处理能力时,就会发生基于堆的缓冲区溢出,从而导致多余的数据溢出到相邻的内存区域.这种溢出会损坏内存,并可能使攻击者能够 ...

  10. .NET Core WebApi接口ip限流实践

    .NET Core WebApi接口ip限流实践 前言 之前一直想实现接口限流,但一直没去实现,然后刚好看到一篇文章是基于AspNetCoreRateLimit 组件的限流策略.这个组件不做多的介绍, ...