首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 .NET Java 游戏 视频 人才 外包 培训 数据库 书店 程序员
中国软件网
欢迎您:游客 | 登录 注册 帮助
  • 【300分放分】一个世界上最懒惰的程序员写的Cache也能让你的复杂计算程序(数据库程序)大大提高速度 [已结帖,结帖人:sp1234]
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • sp1234
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 结帖率:
    发表于:2008-11-24 19:08:16 楼主
    仔细模拟一下你的数据库程序,你有没有发现在计算时(特别是多用户计算时)经常重复读取数据库数据?!这是数据库处理程序的性能的最主要的杀手。

    有些人说在写程序之前应该把算法想好,使得数据记录成批地、一次性地读取。但是这实际上往往不可能,因为复杂的程序贴近逻辑流程才清晰可维护。更何况这也不能解决多用户访问的情况。最好,我们根本不用在写程序时去考虑数据是否会被重复读取从而改变程序流程,但是又能自然而然地防止重复读取数据库。当对计算过程进行优化,而又不想破坏逻辑清晰性的时候,当然就是要依靠简单的Cache —— 对象只要能够缓存几秒钟就好。

    下面我这里写一个世界上最懒惰的程序员使用.net写的一个最简单的Cache,但是它往往可以让复杂的计算程序大大提高计算速度。

    C# code
    using System; using System.Collections.Generic; namespace DomainBase { public class ObjectCache { //Dictionary<K,T> 会自动维护一个空链表来保存不用的单元。 //这里,使用被缓存对象的“弱引用”,允许这些对象被垃圾回收。 private Dictionary<string, WeakReference> Buffer = new Dictionary<string, WeakReference>(); public object this[string key] { get { WeakReference ret; if (Buffer.TryGetValue(key, out ret) && ret.IsAlive) return ret.Target; else return null; } set { WeakReference ret; if (Buffer.TryGetValue(key, out ret)) ret.Target = value; else Buffer.Add(key, new WeakReference(value)); } } public void Remove(string key) { Buffer.Remove(key); } } }


    这就是最简单的Cache。例如:

    public Class User
    {
        static ObjectCache Buffer=new ObjectCache();

        public static GetUser(string id)
        {
          User ret=Buffer[id];
          if(ret==null)
          {
                ret=读取数据库产生User对象(id);
                Buffer[id]=ret;
          }
          return ret;
        }
    .....

    这里,在一个Dictionary <K,T>结构字典中保存了对象的key以及对象的“弱引用”。这样,当内存不足时GC会照样去释放被缓存的对象。当我们需要将对象在几秒钟内进行缓存时,使用这个最简单的Cache很有用。

    .net framework中有非常多非常多的东西需要程序员去了解,不要仅仅抱着那些空洞、不实惠的“放之四海而皆准”的大部头的著作,有时间要多读一些实际地分析 .net framework 系统本身的方面的资料。在每一个技术中都可以找对一两个细节,这个细节就像掌握DNA技术一样能够让你不但扩展原理而且通过动手能力得到巨大实惠。
    300  修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • Old_Mouse
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-24 19:10:371楼 得分:30
    UP
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • yfqvip
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-24 19:11:592楼 得分:30
    先顶在看
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • yfqvip
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-24 19:18:243楼 得分:0
    很简,很实用。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • sp1234
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-24 19:18:414楼 得分:0
    程序示例中可以写

    User ret=Buffer[id] as User;

    类型转换。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • hao1hao2hao3
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-24 19:28:065楼 得分:30
    看看,有时间要多读一些实际地分析 .net framework 系统本身的方面的资料
    这建议不错。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • mjjzg
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-24 19:34:076楼 得分:30
    要看看
    UP
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • qinhl99
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-24 19:37:067楼 得分:30
    学习
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • iuhxq
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-24 19:37:268楼 得分:0
    学习呀
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • hztltgg
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-24 19:41:359楼 得分:30
    学习
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • jjt009
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-24 19:45:1110楼 得分:30
    我顶!顶!顶!
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • qq196260188
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-24 19:47:0811楼 得分:30
    sp1234  支持你

    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • zshengli
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-24 20:02:2812楼 得分:30
    前辈  谢谢分享
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • cj205
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-24 20:04:5913楼 得分:30
    收藏了 sp1234就是sp1234
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • tinalucky
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-24 20:13:5514楼 得分:0
    支持!!
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • oyiboy
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-24 20:16:3315楼 得分:0
    其实我总是一厢情愿的去认为cache会让程序占用内存数字变大。让用户对我的系统产生饭桶(吃太多内存)的感觉。
    之前也用过cache来作东西,但是出现一种很奇怪的现象。某代码如下:
    C# code
    userdata udata=null; if (udata==null) { if(cache.userdata==null) { cache.userdata=new userdata(nowuserid); } udata=cache.userdata; } return udata.name;


    啊,以上代码居然在return udata.name是提示udata==null,真是百思不得其解。后来用户催着出补丁,结果被我改成这样了
    C# code
    userdata udata=null; while (udata == null) { if(cache.userdata==null) { cache.userdata=new userdata(nowuserid); } udata=cache.userdata; } return udata.name;


    当时真的很是纳闷呢。cache丢失得也忒快了点
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • culture9
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-24 20:33:3616楼 得分:0
    小兵来学习
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • amandag
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 2

    发表于:2008-11-24 20:37:1517楼 得分:0
    学习+收藏
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • antiking
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-24 20:45:3418楼 得分:0
    mark
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • xupeihuagudulei
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-24 20:48:4419楼 得分:0
    有些晕

    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • fanliang11
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-24 20:53:2420楼 得分:0
    个人感觉比LZ先进哦。。而且有失效时间,还有LZ没有考虑到一种情况。。并发的情况就没有考虑。。有重大的BUG
    C# code
    using System; using System.Collections.Generic; using System.Collections; using System.Text; using System.Web; using System.Web.Caching; using System.Data; namespace test { /// <summary> /// M缓存类 /// </summary> public class CommonCache { #region 构造函数 /// <summary> /// 静态构造函数 /// </summary> static CommonCache() { } #endregion #region 属性定义 /// <summary> /// 失效时间单位为分钟 /// </summary> public static int LoseTime { set { mLoseTime = value; } } #endregion #region 公共方法 /// <summary> /// 获取值 /// </summary> /// <param name="pKey">键值名</param> /// <returns>返回键值</returns> public static object GetValue(object pKey) { object retValue = null; lock (mCache.SyncRoot) { try { if (mCache.ContainsKey(pKey)) { retValue=mCache[pKey]; IList<object> valueArr = (IList<object>)retValue; DateTime dt = Convert.ToDateTime(valueArr[0]); if (dt.CompareTo(DateTime.Now) < 0) { retValue = null; } else { retValue = valueArr[1]; } } else { retValue = null; } } catch (Exception e) { retValue = null; } } return retValue; } /// <summary> /// 设置值 /// </summary> /// <param name="pKey">键值名</param> /// <param name="pValue">键值</param> public static void SetValue(object pKey, object pValue) { IList<object> valueArr = new List<object>() ; valueArr.Add (DateTime.Now.AddMinutes(mLoseTime)); valueArr.Add ( pValue); lock (mCache.SyncRoot) { try { if (!mCache.ContainsKey(pKey)) { mCache.Add(pKey, valueArr); } else { mCache[pKey] = valueArr; } } catch (Exception e) { } } } #endregion #region 字段定义 /// <summary> /// 缓存对象 /// </summary> private static Hashtable mCache = new Hashtable(); /// <summary> /// 失效时间(单位:分钟) /// </summary> private static int mLoseTime = 60; #endregion } }
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • fanliang11
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-11-24 20:53:3521楼 得分:0
    个人感觉比LZ先进哦。。而且有失效时间,还有LZ没有考虑到一种情况。。并发的情况就没有考虑。。有重大的BUG
    C# code
    using System; using System.Collections.Generic; using System.Collections; using System.Text; using System.Web; using System.Web.Caching; using System.Data; namespace test { /// <summary> /// M缓存类 /// </summary> public class CommonCache { #region 构造函数 /// <summary> /// 静态构造函数 /// </summary> static CommonCache() { } #endregion #region 属性定义 /// <summary> /// 失效时间单位为分钟 /// </summary> public static int LoseTime { set { mLoseTime = value; } } #endregion #region 公共方法 /// <summary> /// 获取值 /// </summary> /// <param name="pKey">键值名</param> /// <returns>返回键值</returns> public static object GetValue(object pKey) { object retValue = null; lock (mCache.SyncRoot) { try { if (mCache.ContainsKey(pKey)) { retValue=mCache[pKey]; IList<object> valueArr = (IList<object>)retValue; DateTime dt = Convert.ToDateTime(valueArr[0]); if (dt.CompareTo(DateTime.Now) < 0) { retValue = null; } else { retValue = valueArr[1]; } } else { retValue = null; } } catch (Exception e) { retValue = null; } } return retValue; } /// <summary> /// 设置值 /// </summary> /// <param name="pKey">键值名</param> /// <param name="pValue">键值</param> public static void SetValue(object pKey, object pValue) { IList<object> valueArr = new List<object>() ; valueArr.Add (DateTime.Now.AddMinutes(mLoseTime)); valueArr.Add ( pValue); lock (mCache.SyncRoot) { try { if (!mCache.ContainsKey(pKey)) { mCache.Add(pKey, valueArr); } else { mCache[pKey] = valueArr; } } catch (Exception e) { } } } #endregion #region 字段定义 /// <summary> /// 缓存对象 /// </summary> private static Hashtable mCache = new Hashtable(); /// <summary> /// 失效时间(单位:分钟) /// </summary>