zoukankan      html  css  js  c++  java
  • PDF.NET开发框架性能剖析

    PDF.NET开发框架性能剖析

    前俩天发布了 关于PDF.NET开发框架对Mysql Sqlite PostgreSQL数据库分页支持的个人看法 ,说明了本人对框架的一些介绍和看法。今天我们一起思考一些问题。

    1.装箱与拆箱

    EntityBase.cs

    复制代码
     1 private object[] values;
     2 /// <summary>
     3 /// 属性值列表
     4 /// </summary>
     5 public virtual object[] PropertyValues
     6 {
     7     get
     8     {
     9         if (values == null)
    10         {
    11             values = new object[PropertyNames.Length];
    12         }
    13         return values;
    14     }
    15     protected internal set { values = value; }
    16 }
    复制代码

    每个实体类对象,一般情况下相当于表中的一行数据。把属性里封装的字段放在数组中,字段有值类型(tinyint int double...) 引用类型,为了满足各种类型只能由object类型出厂,这样会导致值类型频繁进行拆箱(引用类型到值类型--get)/装箱(值类型到引用类型--set)操作.这在一定程度上,对性能造成了损耗。

    2.for与foreach

    CommonDB.cs

    复制代码
     1 if (parameters != null)
     2     for (int i = 0; i < parameters.Length; i++)
     3         if (parameters[i] != null)
     4         {
     5             if (commandType != CommandType.StoredProcedure)
     6             {
     7                 //IDataParameter para = (IDataParameter)((ICloneable)parameters[i]).Clone();
     8                 IDataParameter para = parameters[i];
     9                 if (para.Value == null)
    10                     para.Value = DBNull.Value;
    11                 cmd.Parameters.Add(para);
    12             }
    13             else
    14             {
    15                 //为存储过程带回返回值
    16                 cmd.Parameters.Add(parameters[i]);
    17             }
    18         }
    复制代码

    使用for循环,加数组的索引器使用(每调用一次,就循环一次,可以反编译查看),会造成数组的重复遍历。话不多说,看哥代码,你懂得!

    复制代码
     1 if (parameters != null)
     2 {
     3     foreach (IDataParameter para in parameters)
     4     {
     5         if (para != null)
     6         {
     7             if (commandType != CommandType.StoredProcedure)
     8             {
     9                 if (para.Value == null)
    10                     para.Value = DBNull.Value;
    11                 cmd.Parameters.Add(para);
    12             }
    13             else
    14             {
    15                 //为存储过程带回返回值
    16                 cmd.Parameters.Add(para);
    17             }
    18         }
    19     }
    20 }
    复制代码

    3.双重锁定 double check

    SqlCache.cs

    复制代码
     1 /// <summary>
     2 /// 增加一项到缓存中
     3 /// </summary>
     4 /// <param name="key"></param>
     5 /// <param name="item"></param>
     6 /// <returns></returns>
     7 public static bool AddToCache(string key,SqlInfo item)
     8 {
     9     SqlInfo Value = GetFromCache(key);
    10     if (Value != null)
    11         return false;
    12     lock (sync_obj)
    13     {
    14         DictSqlCache.Add(key, item);
    15     }
    16     return true;
    17 }
    复制代码

    第一个if确实能减少锁的影响,提示性能。 lock里需要做判断的...看代码

    复制代码
     1 /// <summary>
     2 /// 增加一项到缓存中
     3 /// </summary>
     4 /// <param name="key"></param>
     5 /// <param name="item"></param>
     6 /// <returns></returns>
     7 public static bool AddToCache(string key, SqlInfo item)
     8 {
     9     if (!DictSqlCache.ContainsKey(key))//在lock前判断,有助于提升性能
    10     {
    11         lock (sync_obj)//假设2个线程同时执行到这,如果lock里不做判断会出问题
    12         {
    13             if (!DictSqlCache.ContainsKey(key))
    14             {
    15                 DictSqlCache.Add(key, item);
    16                 return true;
    17             }
    18         }
    19     }
    20     return false;
    21 }
    复制代码

    4.分页

    SqlPage.cs

     View Code

    /// <summary>
    /// 根据主键的高效快速分页之 升序分页
    /// </summary>
    /// <param name="pageNum">页码,从1开始</param>
    /// <param name="pageSize">页大小,大于1</param>
    /// <param name="filedList">字段列表</param>
    /// <param name="tableName">表名称</param>
    /// <param name="PKName">主键名称</param>
    /// <param name="conditon">查询条件</param>
    /// <returns>返回指定页码的快速分页SQL语句</returns>
    public static string GetAscPageSQLbyPrimaryKey(int pageNum, int pageSize, string filedList, string tableName, string PKName, string conditon)
    {
    if (conditon == null || conditon == "")
    conditon = "1=1";
    if (pageNum == 1)
    {
    string sqlTemplage = "Select top @pageSize @filedList from @table1 where @conditon order by @PKName desc ";
    return sqlTemplage
    .Replace("@pageSize", pageSize.ToString())
    .Replace("@filedList", filedList)
    .Replace("@table1", tableName)
    .Replace("@conditon", conditon)
    .Replace("@PKName", PKName);
    }
    else
    {
    //@topNum= ((页码-1)*页大小)
    string sqlTemplage = @"
    select top @pageSize @filedList
    from @table1
    where @conditon And @PKName>
    (select max (@PKName) from
    (select top @topNum @PKName from @table1 where @conditon order by @PKName asc) as T
    )
    order by @PKName asc
    ";
    int topNum = (pageNum - 1) * pageSize;

    return sqlTemplage.Replace("@topNum", topNum.ToString())
    .Replace("@pageSize", pageSize.ToString())
    .Replace("@filedList", filedList)
    .Replace("@table1", tableName)
    .Replace("@conditon", conditon)
    .Replace("@PKName", PKName);

    }
    }

     首先,要把字符串对象构造为StringBuilder对象,用StringBuilder对象的Replace方法,这些细节和上篇也提到了,很多人会认为这是废话,好吧......我不说废话了,进入重点。

    看了很多分页代码,有not in的,rownum伪列的,limit的。但如果只根据一列进行查询,主键列或其他值类型的列均可,这种分页无疑是性能最高的。个人很欣赏作者的代码。

    但是,我想提一个问题,

    假如tableName参数传入的是一个viewName(视图名称),

    而这个视图是有10张同结构的表,或不同结构的表抽取意义相同的列的数据  union而成。

    这个视图数据量百万级数据量。这么写能禁得住考验吗?

    那么该如何改进呢?

    相信clever的你已经懂了,若还没想通,那就经历3重境界吧:

       昨夜西风凋碧树,独上高楼,望尽天涯路。

       衣带渐宽终不悔,为伊消得人憔悴。

       然后是蓦然回首...........

     
     
     
    标签: c#性能分页pdf.netwinformasp.net
  • 相关阅读:
    使用supervisor做进程控制
    HDU 4272 LianLianKan [状态压缩DP]
    UVALive 4297 First Knight [期望+高斯消元(优化)]
    HDU 4269 Defend Jian Ge [模拟]
    POJ 2497 Widget Factory [高斯消元解同余方程组]
    HDU 2996 In case of failure [KD树]
    HDU 4268 Alice and Bob [贪心]
    HDU 4273 Rescue [三维几何]
    HDU 4267 A Simple Problem with Integers [树状数组]
    HDU 4271 Find Black Hand [最短编辑距离DP]
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3304356.html
Copyright © 2011-2022 走看看