• 『性能』测试一下 MSSqlHelper 的性能


    本文没啥技术含量,就是测试一下 MSSqlHelper 在 使用反射、不使用反射 的性能对比。

    之后,不要问为什么不用 ORM 这类的东西 —— 会有另外的文章 介绍 自己这些年 自己的ORM 升级历史。

    背景:

    我自己有一个 MSSqlHelper, 这个 辅助类  是最基本的一个 数据库操作类。

    Query 查询集合时,可以指定  reader => 对象  的委托 —— 如果不指定,则 MSSqlHelper 会自动通过反射赋值。

            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 内置的委托 进行了稳定性控制,使用了 这类代码:

    item.FId = Tools.ToLong(reader["FId"]);
    item.FName = Tools.ToString("FName");

     这类转换函数,性能肯定没有 下面的代码 性能快:

    item.FId = (Int64)reader["FId"]; 
    item.FName = (string)reader["FName"];
    

    我为什么死活坚持 Tools 提供的 类型强转?

    > 因为稳定

    > 转换范围广 : 兼容下面这类 变态数据库数据 

    //这是 浏览器的 时间格式,以下代码 能得到 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 的类型转换会浪费多少性能

            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 代码,性能还能再次提升,但我懒得写。

    ----------------------------------------------------------------------------------------------------------------------------------------

    增加了一个 最原生写法 —— 也就是 性能极限

            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高速反射

  • 相关阅读:
    Tina系统的安装
    检查有无相机的权限
    BarEasy打印小程序_CS
    js的websocket
    生成GUID
    读取excel数据到数据库里
    字符串trim
    使用 runOnUiThread在线程内更新UI
    PdfDocument生成PDF,总是产生空文件
    打印36进制的条码序列号
  • 原文地址:https://www.cnblogs.com/shuxiaolong/p/20180722_0147.html
Copyright © 2020-2023  润新知