ASP.NET的输出缓存(即静态HTML)在.NET4.0前一直是基于内存的。这意味着如果我们的站点含有大量的缓存,则很容易消耗掉本机内存。现在,借助于.NET4.0中的OutputCacheProvider,我们可以有多种选择创建自己的缓存。如,我们可以把HTML输出缓存存储到memcached分布式集群服务器,或者MongoDB中(一种常用的面向文档数据库,不妨阅读本篇http://msdn.microsoft.com/zh-cn/magazine/gg650661.aspx)。当然,我们也可以把缓存作为文件存储到硬盘上,考虑到可扩展性,这是一种最廉价的做法,本文就是介绍如果构建自定义文件缓存。

1:OutputCacheProvider

OutputCacheProvider是一个抽象基类,我们需要override其中的四个方法,它们分别是:

Add 方法,将指定项插入输出缓存中。

Get 方法,返回对输出缓存中指定项的引用。

Remove 方法,从输出缓存中移除指定项。

Set 方法,将指定项插入输出缓存中,如果该项已缓存,则覆盖该项。

2:创建自己的文件缓存处理类

该类型为FileCacheProvider,代码如下:

  1. public class FileCacheProvider : OutputCacheProvider
  2. {
  3. private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
  4.  public override void Initialize(string name, NameValueCollection attributes)
  5. {
  6. base.Initialize(name, attributes);
  7. CachePath = HttpContext.Current.Server.MapPath(attributes["cachePath"]);
  8. }
  9. public override object Add(string key, object entry, DateTime utcExpiry)
  10. {
  11. Object obj = Get(key);
  12. if (obj != null) //这一步很重要
  13. {
  14. return obj;
  15. }
  16. Set(key,entry,utcExpiry);
  17. return entry;
  18. }
  19. public override object Get(string key)
  20. {
  21. string path = ConvertKeyToPath(key);
  22. if (!File.Exists(path))
  23. {
  24. return null;
  25. }
  26. CacheItem item = null;
  27. using (FileStream file = File.OpenRead(path))
  28. {
  29. var formatter = new BinaryFormatter();
  30. item = (CacheItem)formatter.Deserialize(file);
  31. }
  32. if (item.ExpiryDate <= DateTime.Now.ToUniversalTime())
  33. {
  34. log.Info(item.ExpiryDate + "*" + key);
  35. Remove(key);
  36. return null;
  37. }
  38. return item.Item;
  39. }
  40. public override void Set(string key, object entry, DateTime utcExpiry)
  41. {
  42. CacheItem item = new CacheItem(entry, utcExpiry);
  43. string path = ConvertKeyToPath(key);
  44. using (FileStream file = File.OpenWrite(path))
  45. {
  46. BinaryFormatter formatter = new BinaryFormatter();
  47. formatter.Serialize(file, item);
  48. }
  49. }
  50. public override void Remove(string key)
  51. {
  52. string path = ConvertKeyToPath(key);
  53. if (File.Exists(path))
  54. File.Delete(path);
  55.  }
  56. public string CachePath
  57. {
  58. get;
  59. set;
  60. }
  61. private string ConvertKeyToPath(string key)
  62. {
  63. string file = key.Replace('/', '-');
  64. file += ".txt";
  65. return Path.Combine(CachePath, file);
  66. }
  67. }
  68. [Serializable]
  69. public class CacheItem
  70. {
  71. public DateTime ExpiryDate;
  72. public object Item;
  73. public CacheItem(object entry, DateTime utcExpiry)
  74. {
  75. Item = entry;
  76. ExpiryDate = utcExpiry;
  77. }
  78. }

有两个地方需要特别说明:

在Add方法中,有一个条件判断,必须做出这样的处理,否则缓存机制将会缓存第一次的结果,过了有效期后缓存讲失效并不再重建;

在示例程序中,我们简单的将缓存放到了Cache目录下,在实际的项目实践中,考虑到缓存的页面将是成千上万的,所以我们必须要做目录分级,否则寻找并读取缓存文件将会成为效率瓶颈,这会耗尽CPU。

3:配置文件

我们需要在Web.config中配置缓存处理程序是自定义的FileCacheProvider,即在 <system.web>下添加节点:

  1. <caching>
  2. <outputCache defaultProvider="FileCache">
  3. <providers>
  4. <add name="FileCache" type="MvcApplication2.Common.FileCacheProvider" cachePath="~/Cache" />
  5. </providers>
  6. </outputCache>
  7.  </caching>

4:缓存的使用

我们假设在MVC的控制中使用(如果要在ASP.NET页面中使用,则在页面中包含<%@OutputCache VaryByParam="none" Duration="10" %>),可以看到,Index是未进行输出缓存的,而Index2进行了输出缓存,缓存时间为10秒。

  1. public class HomeController : Controller
  2. {
  3. private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
  4. static string s_conn = "Data Source=192.168.0.77;Initial Catalog=luminjidb;User Id=sa;Password=sa;";
  5. public ActionResult Index()
  6. {
  7. using (DataSet ds = Common.SqlHelper.ExecuteDataset(s_conn, CommandType.Text, "select top 1* from NameTb a, DepTb b where a.DepID = b.ID ORDER BY NEWID()"))
  8. {
  9. ViewBag.Message = ds.Tables[0].Rows[0]["name"].ToString();
  10. }
  11. return View();
  12. }
  13. [OutputCache(Duration = 10, VaryByParam = "none")]
  14. public ActionResult Index2()
  15. {
  16. using (DataSet ds = Common.SqlHelper.ExecuteDataset(s_conn, CommandType.Text, "select top 1* from NameTb a, DepTb b where a.DepID = b.ID ORDER BY NEWID()"))
  17. {
  18. ViewBag.Message = ds.Tables[0].Rows[0]["name"].ToString();
  19. }
  20. return View();
  21. }
  22. }

5:查看下效果

上面的代码,在访问了Index2后,将会在Cache文件夹下产生缓存文件,如下:

现在,我们开始评价下有输出缓存和无输出缓存的性能对比,模拟100个用户并发1000次请求如下:

可以看到,有输出缓存后,吞吐率明显提高了10倍。

6:代码下载

FileCacheProvider的原始代码来自于网络,我修改了其中的BUG,全部代码下载如下:MvcApplication20110907.rar

职业指导:

在使用某一技能三个月后,你还不是专家,即便使用时间是三年,你还不是。马尔科姆·格莱德威尔在《异类》一书中指出,成为一名真正的专家,需要10000小时。10000小时!如果一天用10小时,每天都学习,则大概需要3年时间。如果一天5小时,一年学习200天,则大概需要10年时间。10年!

原文:http://www.cnblogs.com/luminji/archive/2011/09/08/2169955.html

ASP.NET性能优化之构建自定义文件缓存相关推荐

  1. 如何使用HTML5,JavaScript和Bootstrap构建自定义文件上传器

    by Prashant Yadav 通过Prashant Yadav 如何使用HTML5,JavaScript和Bootstrap构建自定义文件上传器 (How to build a custom f ...

  2. ASP.NET性能优化小结(ASP.NETC#)(转)

    原文转自:http://www.jb51.net/article/25937.htm 一.返回多个数据集  检查你的访问数据库的代码,看是否存在着要返回多次的请求.每次往返降低了你的应用程序的每秒能够 ...

  3. Asp.net性能优化-提高ASP.Net应用程序性能的十大方法

    一.返回多个数据集 检查你的访问数据库的代码,看是否存在着要返回多次的请求.每次往返降低了你的应用程序的每秒能够响应请求的次数.通过在单个数据库请求中返回多个结果集,可以减少与数据库通信的时间,使你的 ...

  4. asp.net 性能优化细节

    asp.net程序性能优化的七个方面 (转) 2007-12-27 04:57 一.数据库操作 转自: http://www.itimes.com.cn/blog/205/look.aspx 1.用完 ...

  5. 总结性能优化:构建你的前端知识体系

    浏览器架构 第一阶段:单进程架构(2007年以前) 指的是浏览器的所有功能模块都运行在一个进程里,包括网络线程.插件线程.JavaScript运行环境.渲染引擎和页面,如此多的模块都在一个进程,是浏览 ...

  6. SAP-ABAP性能优化之构建嵌套结构的哈希表

    编者按:      本文的内容是程序性能优化的一种方式. 使用READ TABLE <哈希表> 取代READ TABLE <标准内表>或LOOP AT WHERE <标准 ...

  7. asp.net性能优化

    转载自:http://www.chinaz.com/Program/.NET/103142JH008.html 一.SqlDataRead和Dataset的选择 Sqldataread优点:读取数据非 ...

  8. ASP.NET性能优化之分布式Session

    如果我们正在使用Session,那么构建高性能可扩展的ASP.NET网站,就必须解决分布式Session的架构,因为单服务器的SESSION处理能力会很快出现性能瓶颈,这类问题也被称之为Session ...

  9. 性能优化(6)-文件优化

    文件优化 图像优化 选择正确的图像格式 消除和替换图像 提供缩放的图像资产 图像精灵 延迟加载非关键图像 延迟加载为何有用? 缓存图像资产 预加载关键图像资产 高效压缩图像 使用服务器与 CDN Cl ...

最新文章

  1. [ExtJS5学习笔记]第五节 使用fontawesome给你的extjs5应用添加字体图标
  2. websocket服务器响应头,从服务器发送响应握手后,websocket.onopen不会触发
  3. Pat乙级1011题:A+B和C
  4. linux C语言调用Intel处理器CPUID指令的实例
  5. oracle的clob赋值_oracle 临时clob 和永久clob 的读取操作详解
  6. Windows10桌面美化
  7. 东北大学计算机学院宿舍环境,软件学院二舍A区308寝室
  8. win10、Ubuntu双系统删除Ubuntu的方法
  9. HTML CSS设计与构建网站 ([美]达科特) PDF原版​
  10. RFT API初涉——之解决RFT无法识别windows对话框的问题
  11. 简述自动化测试实习收获
  12. 敏捷開發: 利益相关者的管理
  13. 201711671116《Web开发技术》第三周作业
  14. Pytorch数据使用列表的卷积层时报错及解决-RuntimeError: Input type (torch.cuda.HalfTensor) and weight type (torch.Floa
  15. 快速找到python第三方库
  16. React之SCU(性能优化篇)
  17. 网易博客fengqing888搬家至CSDN啦
  18. Android中设置颜色透明度
  19. 时频分析在工程中的应用
  20. matalb曲线图只有点没有线_老股民教你精准把握买卖点只需一个指标:分时图,学到就是赚到!...

热门文章

  1. 一天的学习成果:hash输出,dcache工作原理,include的home directory,fist optype的含义...
  2. 在php里让字体划过变色,鼠标划过字体时如何用css来实现字体变色?(代码实测)...
  3. WIFI配网方式(AP模式、Smartconfig等模式)
  4. 判断同构数 c语言,基于visual Studio2013解决C语言竞赛题之0413同构数
  5. java 混码_kotlin java 混合代码 maven 打包实现
  6. python可视化界面编程 pycharm_pycharm开发一个简单界面和通用mvc模板(操作方法图解)...
  7. 中文能用rsa加密吗_外文文献数据库能用中文词进行检索吗?
  8. 不要在foreach循环里进行元素的remove/add操作。remove元素请使用iteratot方式,如果并发操作,需要对Iterator对象加锁
  9. Linus中帮助命令man
  10. linux 股票指南针,IOS开发入门之ios指南针