随笔 - 86  文章 - 0  评论 - 737  阅读 - 18万

『性能』测试一下 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高速反射

 

posted on   InkFx  阅读(1069)  评论(1编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 单线程的Redis速度为什么快?
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 展开说说关于C#中ORM框架的用法!
· SQL Server 2025 AI相关能力初探
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
< 2025年3月 >
23 24 25 26 27 28 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 1 2 3 4 5

点击右上角即可分享
微信分享提示