『性能』测试一下 MSSqlHelper 的性能
本文没啥技术含量,就是测试一下 MSSqlHelper 在 使用反射、不使用反射 的性能对比。
之后,不要问为什么不用 ORM 这类的东西 —— 会有另外的文章 介绍 自己这些年 自己的ORM 升级历史。
背景:
我自己有一个 MSSqlHelper, 这个 辅助类 是最基本的一个 数据库操作类。
Query 查询集合时,可以指定 reader => 对象 的委托 —— 如果不指定,则 MSSqlHelper 会自动通过反射赋值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | static void Main( string [] args) { Test0(); Test1(); Test0(); Test1(); Console.ReadKey(); } public static void Test0() { string connString = "Data Source=localhost;Initial Catalog=InkFxBlog;User Id=sa; Pwd=123.com;" ; DateTime time0 = DateTime.Now; List<TS_SDK> list = MSSqlHelper.Query<TS_SDK>(connString, "SELECT * FROM dbo.TS_SDK" ); DateTime time1 = DateTime.Now; Console.WriteLine( "Test0 | " + list.Count + " | " + (time1 - time0).TotalSeconds + "秒" ); } public static void Test1() { string connString = "Data Source=localhost;Initial Catalog=InkFxBlog;User Id=sa; Pwd=123.com;" ; DateTime time0 = DateTime.Now; List<TS_SDK> list = MSSqlHelper.Query<TS_SDK>(connString, "SELECT * FROM dbo.TS_SDK" , null , reader => { TS_SDK item = new TS_SDK(); item.FId = (Int64)reader[ "FId" ]; item.FNumber = ( string )reader[ "FNumber" ]; item.FEnum = ( string )reader[ "FEnum" ]; item.FName = ( string )reader[ "FName" ]; item.FSDKName = ( string )reader[ "FSDKName" ]; item.FFullName = ( string )reader[ "FFullName" ]; item.FType = ( string )reader[ "FType" ]; item.FVisit = ( string )reader[ "FVisit" ]; item.FInheritFrom = ( string )reader[ "FInheritFrom" ]; item.FJoinBaseType = ( string )reader[ "FJoinBaseType" ]; item.FJoinChildType = ( string )reader[ "FJoinChildType" ]; item.FIsStatic = (Boolean)reader[ "FIsStatic" ]; item.FIsOverride = (Boolean)reader[ "FIsOverride" ]; item.FIsVirtual = (Boolean)reader[ "FIsVirtual" ]; item.FIsAbstract = (Boolean)reader[ "FIsAbstract" ]; item.FIsInherit = (Boolean)reader[ "FIsInherit" ]; item.FIsNetFx = (Boolean)reader[ "FIsNetFx" ]; item.FOutUrl = ( string )reader[ "FOutUrl" ]; item.FSummary = ( string )reader[ "FSummary" ]; item.FRtSummary = ( string )reader[ "FRtSummary" ]; item.FCSCode = ( string )reader[ "FCSCode" ]; item.FVBCode = ( string )reader[ "FVBCode" ]; item.FCPPCode = ( string )reader[ "FCPPCode" ]; item.FFSCode = ( string )reader[ "FFSCode" ]; item.FAssembly = ( string )reader[ "FAssembly" ]; item.FVersion = ( string )reader[ "FVersion" ]; item.FNameSpace = ( string )reader[ "FNameSpace" ]; item.FParentId = (Int64)reader[ "FParentId" ]; item.FParentNumber = ( string )reader[ "FParentNumber" ]; item.FDemo = ( string )reader[ "FDemo" ]; item.FInfo = ( string )reader[ "FInfo" ]; return item; }); DateTime time1 = DateTime.Now; Console.WriteLine( "Test1 | " + list.Count + " | " + (time1 - time0).TotalSeconds + "秒" ); } |
运行结果:
读取了全表 7W行记录。
—— 很明显:没有指定 reader 读取的委托、使用内置的反射代码 足足慢了 3秒。
—— 当然,MSSqlHelper 内置的委托 进行了稳定性控制,使用了 这类代码:
1 2 | item.FId = Tools.ToLong(reader[ "FId" ]); item.FName = Tools.ToString( "FName" ); |
这类转换函数,性能肯定没有 下面的代码 性能快:
1 2 | item.FId = (Int64)reader[ "FId" ]; item.FName = ( string )reader[ "FName" ]; |
我为什么死活坚持 Tools 提供的 类型强转?
> 因为稳定
> 转换范围广 : 兼容下面这类 变态数据库数据
1 2 3 4 5 | //这是 浏览器的 时间格式,以下代码 能得到 2017-03-20 02:46:06 000 DateTime timeA = Tools.ToDateTime( "Mon Mar 20 2017 02:46:06 GMT+0800 (中国标准时间)" ); //以下代码 能得到 2017-03-19 01:43:15 000 DateTime timeA = Tools.ToDateTime( "2017年3月19日 01时43分15秒" ); |
我们再使用 Tools 的类型强转函数 试一试,看一下 Tools 的类型转换会浪费多少性能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | public static void Test2() { string connString = "Data Source=localhost;Initial Catalog=InkFxBlog;User Id=sa; Pwd=123.com;" ; DateTime time0 = DateTime.Now; List<TS_SDK> list = MSSqlHelper.Query<TS_SDK>(connString, "SELECT * FROM dbo.TS_SDK" , null , reader => { TS_SDK item = new TS_SDK(); //这次的 reader 委托, //类型转换 使用的 Tools.ToLong() Tools.ToLong() 这类函数 //为什么不直接用 (string)reader["FName"] 这类直接转换 ? —— 为了稳定性、我宁愿牺牲性能 item.FId = Tools.ToLong(reader[ "FId" ]); item.FNumber = Tools.ToString(reader[ "FNumber" ]); item.FEnum = Tools.ToString(reader[ "FEnum" ]); item.FName = Tools.ToString(reader[ "FName" ]); item.FSDKName = Tools.ToString(reader[ "FSDKName" ]); item.FFullName = Tools.ToString(reader[ "FFullName" ]); item.FType = Tools.ToString(reader[ "FType" ]); item.FVisit = Tools.ToString(reader[ "FVisit" ]); item.FInheritFrom = Tools.ToString(reader[ "FInheritFrom" ]); item.FJoinBaseType = Tools.ToString(reader[ "FJoinBaseType" ]); item.FJoinChildType = Tools.ToString(reader[ "FJoinChildType" ]); item.FIsStatic = Tools.ToBoolean(reader[ "FIsStatic" ]); item.FIsOverride = Tools.ToBoolean(reader[ "FIsOverride" ]); item.FIsVirtual = Tools.ToBoolean(reader[ "FIsVirtual" ]); item.FIsAbstract = Tools.ToBoolean(reader[ "FIsAbstract" ]); item.FIsInherit = Tools.ToBoolean(reader[ "FIsInherit" ]); item.FIsNetFx = Tools.ToBoolean(reader[ "FIsNetFx" ]); item.FOutUrl = Tools.ToString(reader[ "FOutUrl" ]); item.FSummary = Tools.ToString(reader[ "FSummary" ]); item.FRtSummary = Tools.ToString(reader[ "FRtSummary" ]); item.FCSCode = Tools.ToString(reader[ "FCSCode" ]); item.FVBCode = Tools.ToString(reader[ "FVBCode" ]); item.FCPPCode = Tools.ToString(reader[ "FCPPCode" ]); item.FFSCode = Tools.ToString(reader[ "FFSCode" ]); item.FAssembly = Tools.ToString(reader[ "FAssembly" ]); item.FVersion = Tools.ToString(reader[ "FVersion" ]); item.FNameSpace = Tools.ToString(reader[ "FNameSpace" ]); item.FParentId = Tools.ToLong(reader[ "FParentId" ]); item.FParentNumber = Tools.ToString(reader[ "FParentNumber" ]); item.FDemo = Tools.ToString(reader[ "FDemo" ]); item.FInfo = Tools.ToString(reader[ "FInfo" ]); return item; }); DateTime time1 = DateTime.Now; Console.WriteLine( "Test2 | " + list.Count + " | " + (time1 - time0).TotalSeconds + "秒" ); } |
再测试一下:
—— 近期想把自己的底层辅助类 再优化一下,所以把代码翻出来,折腾一下 ~
----------------------------------------------------------------------------------------------------------------------------------------
刚刚修改了一下 反射的代码,启用了 Emit 高速反射
性能果然得到了 明显提升,性能仅损失 15 ~20% —— 我已经知足了。
Ps. 目前的 Emit反射 使用的通用代码(内外一个辅助类) —— 如果针对性的写 Emit 代码,性能还能再次提升,但我懒得写。
----------------------------------------------------------------------------------------------------------------------------------------
增加了一个 最原生写法 —— 也就是 性能极限
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | public static void TestSouce() { string connString = "Data Source=localhost;Initial Catalog=InkFxBlog;User Id=sa; Pwd=123.com;" ; DateTime time0 = DateTime.Now; List<TS_SDK> list = new List<TS_SDK>(); using (SqlConnection conn = new SqlConnection(connString)) { conn.Open(); using (SqlCommand cmd = conn.CreateCommand()) { cmd.CommandText = "SELECT * FROM dbo.TS_SDK" ; using (SqlDataReader reader = cmd.ExecuteReader()) { while (reader.Read()) { TS_SDK item = new TS_SDK(); item.FId = (Int64)reader[ "FId" ]; item.FNumber = ( string )reader[ "FNumber" ]; item.FEnum = ( string )reader[ "FEnum" ]; item.FName = ( string )reader[ "FName" ]; item.FSDKName = ( string )reader[ "FSDKName" ]; item.FFullName = ( string )reader[ "FFullName" ]; item.FType = ( string )reader[ "FType" ]; item.FVisit = ( string )reader[ "FVisit" ]; item.FInheritFrom = ( string )reader[ "FInheritFrom" ]; item.FJoinBaseType = ( string )reader[ "FJoinBaseType" ]; item.FJoinChildType = ( string )reader[ "FJoinChildType" ]; item.FIsStatic = (Boolean)reader[ "FIsStatic" ]; item.FIsOverride = (Boolean)reader[ "FIsOverride" ]; item.FIsVirtual = (Boolean)reader[ "FIsVirtual" ]; item.FIsAbstract = (Boolean)reader[ "FIsAbstract" ]; item.FIsInherit = (Boolean)reader[ "FIsInherit" ]; item.FIsNetFx = (Boolean)reader[ "FIsNetFx" ]; item.FOutUrl = ( string )reader[ "FOutUrl" ]; item.FSummary = ( string )reader[ "FSummary" ]; item.FRtSummary = ( string )reader[ "FRtSummary" ]; item.FCSCode = ( string )reader[ "FCSCode" ]; item.FVBCode = ( string )reader[ "FVBCode" ]; item.FCPPCode = ( string )reader[ "FCPPCode" ]; item.FFSCode = ( string )reader[ "FFSCode" ]; item.FAssembly = ( string )reader[ "FAssembly" ]; item.FVersion = ( string )reader[ "FVersion" ]; item.FNameSpace = ( string )reader[ "FNameSpace" ]; item.FParentId = (Int64)reader[ "FParentId" ]; item.FParentNumber = ( string )reader[ "FParentNumber" ]; item.FDemo = ( string )reader[ "FDemo" ]; item.FInfo = ( string )reader[ "FInfo" ]; list.Add(item); } } } } DateTime time1 = DateTime.Now; Console.WriteLine( "TestSouce | " + list.Count + " | " + (time1 - time0).TotalSeconds + "秒" ); } |
----------------------------------------------------------------------------------------------------------------------------------------
彻底完成,性能已经到达极限
PS. 笔误: Emit高速反射
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 单线程的Redis速度为什么快?
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 展开说说关于C#中ORM框架的用法!
· SQL Server 2025 AI相关能力初探
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库