一个基于 SourceGenerator 生成 从 dbReader转换为 class 数据的性能测试实验
好奇
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 数据的性能测试实验的更多相关文章
- 一个基于图的数据管理系统-gStore
gStore是遵循 BSD协议的一个开源项目.一个基于图的 RDF 三元组存储的数据管理系统.该项目是北京大学.滑铁卢大学.香港科技大学的联合研究项目.中国北京大学计算机科学与技术研究所的数据库组对该 ...
- 基于Thinkphp5+phpQuery 网络爬虫抓取数据接口,统一输出接口数据api
TP5_Splider 一个基于Thinkphp5+phpQuery 网络爬虫抓取数据接口 统一输出接口数据api.适合正在学习Vue,AngularJs框架学习 开发demo,需要接口并保证接口不跨 ...
- 一个基于原生JavaScript开发的、轻量的验证码生成插件
Vcode.js 一个基于原生JavaScript开发的.轻量的验证码生成插件 V: 1.0.0 DEMO:https://jofunliang.github.io/Vcode.js/example. ...
- 一个基于.NET平台的自动化/压力测试系统设计简述
AutoTest系统设计概述 AutoTest是一个基于.NET平台实现的自动化/压力测试的系统,可独立运行于windows平台下,支持分布式部署,不需要其他配置或编译器的支持.(本质是一个基于协议的 ...
- 构建一个基于 Spring 的 RESTful Web Service
本文详细介绍了基于Spring创建一个“hello world” RESTful web service工程的步骤. 目标 构建一个service,接收如下HTTP GET请求: http://loc ...
- TensorFlow练习7: 基于RNN生成古诗词
http://blog.topspeedsnail.com/archives/10542 主题 TensorFlow RNN不像传统的神经网络-它们的输出输出是固定的,而RNN允许我们输入输出向量 ...
- RSuite 一个基于 React.js 的 Web 组件库
RSuite http://rsuite.github.io RSuite 是一个基于 React.js 开发的 Web 组件库,参考 Bootstrap 设计,提供其中常用组件,支持响应式布局. 我 ...
- Linux下c基于openssl生成MD5的函数
Linux下openssl提供了一系列哈希及加密的函数,如果调用openssl提供的MD5函数生成任意字符串的MD5呢?下面提供了一段代码实现Linux下c字符串生成md5的函数. 具体代码: 1 2 ...
- 一个基于nodejs,支持http/https的中间人(MITM)代理,便于渗透测试和开发调试。
源码地址:https://github.com/wuchangming/node-mitmproxy node-mitmproxy node-mitmproxy是一个基于nodejs,支持http/h ...
- 一个基于ES6+webpack的vue小demo
上一篇文章<一个基于ES5的vue小demo>我们讲了如何用ES5,vue-router做一个小demo,接下来我们来把它变成基于ES6+webpack的demo. 一.环境搭建及代码转换 ...
随机推荐
- Dijkstra(迪杰斯特拉)算法
Dijkstra是什么算法 Dijkstra是典型最短路径算法,用于计算一个节点到其他节点的最短路径.该算法使用的是贪心策略:每次都找出剩余顶点中与源点距离最近的一个顶点. 什么是最短路径问题 给定 ...
- The requested operation cannot be completed because the connection has been broken
具体报错 The requested operation cannot be completed because the connection has been broken. -- xxxForyy ...
- mysql报错 a foreign key constraint fails(外键约束错误)
报错信息如下: (pymysql.err.IntegrityError) (1452, u'Cannot add or update a child row: a foreign key constr ...
- Next.js 13 如何使用loading.js
要在next.js 13中使用loading.js,我们需要先在对应的文件目录下创建loading.js文件 文件结构如下: app test1 loading.tsx page.tsx 如上面的目录 ...
- C#.NET与JAVA互通之MD5哈希V2024
C#.NET与JAVA互通之MD5哈希V2024 配套视频: 要点: 1.计算MD5时,SDK自带的计算哈希(ComputeHash)方法,输入输出参数都是byte数组.就涉及到字符串转byte数组转 ...
- @ConfigurationProperties(prefix = “xx.xx.xx“) 从配置文件中取值赋给类的属性
@ConfigurationProperties(prefix = "xx.xx.xx") 从配置文件中取值赋给类的属性 @ConfigurationProperties(pref ...
- linux安装redis完整步骤
linux安装redis完整步骤 安装:1.获取redis资源 wget http://download.redis.io/releases/redis-4.0.8.tar.gz 2.解压 tar x ...
- 网络诊断工具iPerf的使用
iPerf 是一个网络性能测试工具,用于测量最大 TCP 和 UDP 带宽性能.它支持多种平台,包括 Windows.Linux.macOS 等.以下是 iPerf 的基本使用方法: 安装 iPerf ...
- Jupyter QtConsole 配置,2023 年了你还在使用 QtConsole 吗?
目录 Jupyter QtConsole 配置,2023 年了你还在使用 QtConsole 吗? Jupyter QtConsole 的安装 设置字体 启动时自动加载需要的库包 更新:2023 年 ...
- 支持TraceID、错误文件、错误行的第三方golang库:gerror
Gerr库简介 Golang第三方库 官方仓库:https://github.com/GuoFlight/gerror 特点: 兼容golang原生error库 gerror会自动生成traceID, ...