第六篇性能优化 在计算机科学领域,广泛应用缓冲技术来提高系统的性能,它的原理是把经常存取的或 者是比较重要的数据保存于内存中以减少系统的响应时间。对于WEB应用领域,缓冲技术 主要是把HTTP请求的页面或数据保存于内存,以减少下次使用时重建它们的耗费 ASPNET有两种用于WEB应用的缓冲技术:输出缓冲和数据缓冲 输出缓冲指:把一次请求所产生的动态输出保存于内存中。 数据缓冲指:按照一定的策略把事先不确定的对象保存于内存中。 输出缓冲常用于把整个输出页面缓冲起来。对于一个存取繁忙的站点来说,把一些常用 页面放入内存会带来性能上的极大提高。当一个页面被放入输出缓存,那么接下来的对该页 面的请求将不再执行创建它的代码,而是从内存中直接返回该页面。 但实际上,保存整个输出页面的方法并不一定都行得通,因为有些页面的输出取决于客 户端的不同请求,称之为“定制”。这时,采取的方法即找出不同中的相同,把一些并不需 要经常重新创建的对象和数据识别出来,进行缓冲。一旦这些部分被识别,那么它们将被 次创建并在缓存中保持一定的时间。 选择缓存的时间是提高性能的关键。对一些部分来说,它们需要隔一定时间进行刷新, 而另一些部分来说,可能仅仅只是需要保存一段时间。此种情况下,都可以设定“过期策略” 来实现。一旦这些对象和数据到期,它们都将被从缓存中清除出去。当存取对象和数据的代 码发现所要求的部分在内存中不存在时,将重建该对象或数据 ASPNET支持文件和缓存关键字的依赖关系,它允许开发人员创建缓存依赖于一个外 部文件或另一个缓存事物。利用这项技术可以更新一个缓存事物当其依赖的源文件发生改变 第一章页面输出缓存 611基本概念 页面输出缓存通过保存动态页面的输出内容,大大提高了服务器应用的能力。缺省情况 下,输出缓存选项是被打开的,但并不是任意给定的输出响应都将被缓存,除非显示地指定 页面应被缓存 为使输出能够被缓存,输出响应至少应有一个有效的过期/有效策略以及公用 cache的 访问权限。当一个GET请求被送往页面,一个输出缓冲入口将被创建。接下来,对该页面 的GET请求和HEAD的请求将直接从该缓冲入口中取出返回给用户,而对该页面的POST 请求通常是显示地产生动态内容,却并非如同GET和HEAD请求一样从缓冲入口中取出。 输出缓存还支持带请求串的GET方法,把请求串作为页面识别的一部分。这就意味着 带有相同键值但排列次序不同的请求串的GET请求,可能导致缓存中认为不存在该输出页 面 输出缓存需要知道页面缓存的过期/有效时间策略。如果一个页面在输出缓存中,而且 又被指定为60分钟的页面过期时间,那么从它进入输出缓存开始,60分钟后该页面将从输 出缓存中被清除。如果恰在此时,有一个对该页面的请求到达,页面的代码将被执行,页面
第六篇 性能优化 在计算机科学领域,广泛应用缓冲技术来提高系统的性能,它的原理是把经常存取的或 者是比较重要的数据保存于内存中以减少系统的响应时间。对于 WEB 应用领域,缓冲技术 主要是把 HTTP 请求的页面或数据保存于内存,以减少下次使用时重建它们的耗费。 ASP.NET 有两种用于 WEB 应用的缓冲技术:输出缓冲和数据缓冲。 输出缓冲指:把一次请求所产生的动态输出保存于内存中。 数据缓冲指:按照一定的策略把事先不确定的对象保存于内存中。 输出缓冲常用于把整个输出页面缓冲起来。对于一个存取繁忙的站点来说,把一些常用 页面放入内存会带来性能上的极大提高。当一个页面被放入输出缓存,那么接下来的对该页 面的请求将不再执行创建它的代码,而是从内存中直接返回该页面。 但实际上,保存整个输出页面的方法并不一定都行得通,因为有些页面的输出取决于客 户端的不同请求,称之为“定制”。这时,采取的方法即找出不同中的相同,把一些并不需 要经常重新创建的对象和数据识别出来,进行缓冲。一旦这些部分被识别,那么它们将被一 次创建并在缓存中保持一定的时间。 选择缓存的时间是提高性能的关键。对一些部分来说,它们需要隔一定时间进行刷新, 而另一些部分来说,可能仅仅只是需要保存一段时间。此种情况下,都可以设定“过期策略” 来实现。一旦这些对象和数据到期,它们都将被从缓存中清除出去。当存取对象和数据的代 码发现所要求的部分在内存中不存在时,将重建该对象或数据。 ASP.NET 支持文件和缓存关键字的依赖关系,它允许开发人员创建缓存依赖于一个外 部文件或另一个缓存事物。利用这项技术可以更新一个缓存事物当其依赖的源文件发生改变 时。 第一章 页面输出缓存 6.1.1 基本概念 页面输出缓存通过保存动态页面的输出内容,大大提高了服务器应用的能力。缺省情况 下,输出缓存选项是被打开的,但并不是任意给定的输出响应都将被缓存,除非显示地指定 页面应被缓存。 为使输出能够被缓存,输出响应至少应有一个有效的过期/有效策略以及公用 cache 的 访问权限。当一个 GET 请求被送往页面,一个输出缓冲入口将被创建。接下来,对该页面 的 GET 请求和 HEAD 的请求将直接从该缓冲入口中取出返回给用户,而对该页面的 POST 请求通常是显示地产生动态内容,却并非如同 GET 和 HEAD 请求一样从缓冲入口中取出。 输出缓存还支持带请求串的 GET 方法,把请求串作为页面识别的一部分。这就意味着 带有相同键值但排列次序不同的请求串的 GET 请求,可能导致缓存中认为不存在该输出页 面。 输出缓存需要知道页面缓存的过期/有效时间策略。如果一个页面在输出缓存中,而且 又被指定为 60 分钟的页面过期时间,那么从它进入输出缓存开始,60 分钟后该页面将从输 出缓存中被清除。如果恰在此时,有一个对该页面的请求到达,页面的代码将被执行,页面
输出又将重新进入输出缓冲。这种方式的过期策略称之为“强制过期”,页面只在一定时间 内有效。 如下,我们可以用下面一条语句来显示的指出页面在输出缓冲中的保存时间。 612实例 下面举一个简单的例子来证实 ASPNET中的页面缓存功能 在一个页加载时,我们显示它的时间,在页面过期时间(设为:10秒)到达之前,我 们把页面刷新(相当于重发GET请求),看一看显示的时间;然后,在过期时间到达之后, 再看显示的时间。如果,第一次和第二次显示的时间相同,那么就证明了,系统存在有页面 输出缓存功能,做为对比,当过期时间到达后,新的请求将导致重新执行页面代码,产生新 的时间显示。 程序源程序 页面输出缓存测试 Sub Page Load(s As Object, EAs EventArgs) IbITime.Text="现在时间是:"& DateTime. now. ToString End sub body> 测试页面输出缓存实验 / body> 第一次输出效果
输出又将重新进入输出缓冲。这种方式的过期策略称之为“强制过期”,页面只在一定时间 内有效。 如下,我们可以用下面一条语句来显示的指出页面在输出缓冲中的保存时间。 6.1.2 实例 下面举一个简单的例子来证实 ASP.NET 中的页面缓存功能 在一个页加载时,我们显示它的时间,在页面过期时间(设为:10 秒)到达之前,我 们把页面刷新(相当于重发 GET 请求),看一看显示的时间;然后,在过期时间到达之后, 再看显示的时间。如果,第一次和第二次显示的时间相同,那么就证明了,系统存在有页面 输出缓存功能,做为对比,当过期时间到达后,新的请求将导致重新执行页面代码,产生新 的时间显示。 程序源程序 页面输出缓存测试 Sub Page_Load(s As Object, E As EventArgs) lblTime.Text ="现在时间是:" & DateTime.Now.ToString() End Sub 测试页面输出缓存实验 第一次输出效果:
页面输出线存测试-" microsoft Internet Explorer 文件)编辑)查看收藏A)工具①)帮助① 测试页面输出缓存实验 现在时间是2001-03-251121842 「本地 Intranet 第二次输出效果 页面输出缓存测试-" icrosoft Internet Explorer 文件)编辑)查看)收藏④)工具①)帮助 加·翩發藏晶 测试页面输出缓存实验 现在时间是2001-03-25121842 完成 本地 Intranet 第三次输出效果:
第二次输出效果: 第三次输出效果:
回页面输出缓存训试 MicrosoftInternetExplorer 文件①)编辑¢)查看Q收藏()工具〔)帮助Q 测试页面输出缓存实验 现在时间是2001-03-25T1221:13 完成 本地 intranet 实现页面缓存的另一种方法: 指定页面输出缓存下一个10秒到期 Response Cache. SetExpires( DateTime. Now. AddSeconds(10)) 指定所有用户都有对缓存的访问权力 ResponseCacheSetCacheability(httpcacheability.Public) 如果不希望进行页面缓存,可采用 Response Cache. SetSliding Expiration方法,当其为True 时,每次页面请求到达时,相当于页面过期时间到了,就要对页面输出重新刷新 当每次页面请求时,重置到期时间计数器,并且页面到期 Response Cache. SetSliding Expiration(True) 例如上面的例子可以改写成如下例子: %@ iMport Name space="sysTem. Web. hTtp Cache policy"%> 页面输出缓存测试
实现页面缓存的另一种方法: ‘指定页面输出缓存下一个 10 秒到期 Response.Cache.SetExpires(DateTime.Now.AddSeconds(10)) ‘指定所有用户都有对缓存的访问权力 Response.Cache.SetCacheability(HttpCacheability.Public) 如果不希望进行页面缓存,可采用Response.Cache.SetSlidingExpiration 方法,当其为True 时,每次页面请求到达时,相当于页面过期时间到了,就要对页面输出重新刷新 。 ‘当每次页面请求时,重置到期时间计数器,并且页面到期 Response.Cache.SetSlidingExpiration(True) 例如上面的例子可以改写成如下例子: 页面输出缓存测试 1
Sub Page Load(s As Object, EAs EventArgs) response cache. setexpires( Date Time Now. addseconds( 10)) response.cache.setcacheability(httpcacheability.Public) IblTime. Text="现在时间是:"& DateTime. Now ToString( End Sub 测试页面输出缓存实验1 asp: label id="lblTime"runat="server"A> /html> 输出的结果和上一例子大体相同,就不在重复了 另外,在ASP中,对于上面的例子我们还可以写为 Response Cache Control ="Public res= 10 从兼容性出发, ASPNET中依然具有相同的效果,但建议尽量使用 ASPNET的形式。 613小结 本章介绍了页面输出缓存的基本概念,以及在 asp. net中如何通过page命令和 response 对象在编程中实现页面输出缓存的实现方法。 第二章页面数据缓存 621基本概念 ASPNET提供了一个相当出色的缓存引擎机制,它允许页面保存和索引HTTP请求所 要求的各种各样的对象。 ASPNET的缓存对各个应用来说是私有的,是存储各种对象的存 储器。缓存的生存周期取决于应用的生存周期,也就是说,当应用重新启动时,缓存实际上 也已重建。 缓存提供了一个简单的字典接口,以便于开发者能够轻而易举放置对象到缓存中,并在 以后使用。最简单的情况下,放置一个对象到缓存中,就如同对字典增加一个条目 例如: 即是把 My Value放入缓存中一个叫 myKey的缓存对象中,当需要引用 myKey值时 可以采用下面的使用方式: my Value l=Cache("myKey") if my valuel Null then
Sub Page_Load(s As Object, E As EventArgs) response.cache.setexpires(DateTime.Now.addseconds(10)) response.cache.setcacheability(Httpcacheability.Public) lblTime.Text ="现在时间是:" & DateTime.Now.ToString() End Sub 测试页面输出缓存实验 1 输出的结果和上一例子大体相同,就不在重复了。 另外,在 ASP 中,对于上面的例子我们还可以写为: Response.CacheControl = "Public" Response.Expires = 10 从兼容性出发,ASP.NET 中依然具有相同的效果,但建议尽量使用 ASP.NET 的形式。 6.1.3 小结 本章介绍了页面输出缓存的基本概念,以及在 asp.net 中如何通过 page 命令和 response 对象在编程中实现页面输出缓存的实现方法。 第二章 页面数据缓存 6.2.1 基本概念 ASP.NET 提供了一个相当出色的缓存引擎机制,它允许页面保存和索引 HTTP 请求所 要求的各种各样的对象。ASP.NET 的缓存对各个应用来说是私有的,是存储各种对象的存 储器。缓存的生存周期取决于应用的生存周期,也就是说,当应用重新启动时,缓存实际上 也已重建。 缓存提供了一个简单的字典接口,以便于开发者能够轻而易举放置对象到缓存中,并在 以后使用。最简单的情况下,放置一个对象到缓存中,就如同对字典增加一个条目。 例如: Cache(“myKey”)=MyValue 即是把 MyValue 放入缓存中一个叫 myKey 的缓存对象中,当需要引用 myKey 值时, 可以采用下面的使用方式: myValue1=Cache(“myKey”) if myValue1 <> Null then
非空时的动作 d if asp. net提供了三种缓存替换的策略 1.“腐烂搜索”( Scavenging) 比较类似于“最近最少使用”替换原则,当内存变得比教紧张时,缓存机制会找出最不 常用和最不重要的对象,把它从内存中移出,以减轻系统压力。为控制“腐烂搜索”的具体 行为,编程者必须在插入缓存对象时,指明插入它的耗费和多少时间内它必须被存取一次才 能继续留在缓存中,以供替换时进行决择 2.“到期控制”( Expiration) 编程者可以指定缓存对象的生存周期,这种指定的时间可以是绝对的也可以是相对的。 例如绝对的时间(下午6:00到期),相对时间(该对象距最近一次存取它的时间满10分钟 即到期)。当一个缓存对象到期后,它将从缓冲内存中移出,此时对该对象的索引将得到null 值,除非又重新插入该对象 3.“文件和键值依赖 从外部文件或者是其他缓存键值是否改变,来决定本身键值是否有效。如果依赖发生改 变,缓存对象将变得不可使用,并从缓存中移动出来。试想这样一种情况,应用从一个XML 文件中读出金融信息,而该文件又被定期地修改。应用的作用是利用从该文件读出的信息构 造一个图形对象以表示销售的情况。当应用读入文件时,它把数据插入缓存中,并记录下文 件的依赖关系。当文件发生修改时,应用使开始产生的缓存对象无效并从内存中移出已经无 用的数据,此后应用重新读入文件的数据,再把更新后的数据放入缓存,这样就完成了信息 的更新,并返回给最终用户 622实例 例子: 从一个XML中读出用户信息并显示在页面上,页面提供了两个按钮,一个为增加用户 个为刷新。我们在内存中建立了一个缓存对象“ DataCache5,它与客户信息文件 custom1xm”建立了依赖关系。当 custom 1. xml文件未发生变化时,我们按下“刷新”按钮 可以看到信息是从缓存中读出的:当我们输入客户相应的资料,增加了一个客户以后,再按 下“刷新“按钮后,我们可以看到客户信息变成了从文件读出。 1.ASPX源程序( performance\ FormData Cache. aspx) 当缓存对象 DataCache5有效时,从缓存中读出客户信息:无效时,从文件读出信息 dim dyl as data view dv l=Cache("Data Caches") if dvl= nothing dim ds as dataSe
‘非空时的动作 … end if asp.net 提供了三种缓存替换的策略: 1.“腐烂搜索”(Scavenging) 比较类似于“最近最少使用”替换原则,当内存变得比教紧张时,缓存机制会找出最不 常用和最不重要的对象,把它从内存中移出,以减轻系统压力。为控制“腐烂搜索”的具体 行为,编程者必须在插入缓存对象时,指明插入它的耗费和多少时间内它必须被存取一次才 能继续留在缓存中,以供替换时进行决择。 2.“到期控制”(Expiration) 编程者可以指定缓存对象的生存周期,这种指定的时间可以是绝对的也可以是相对的。 例如绝对的时间(下午 6:00 到期),相对时间(该对象距最近一次存取它的时间满 10 分钟 即到期)。当一个缓存对象到期后,它将从缓冲内存中移出,此时对该对象的索引将得到 null 值,除非又重新插入该对象。 3.“文件和键值依赖” 从外部文件或者是其他缓存键值是否改变,来决定本身键值是否有效。如果依赖发生改 变,缓存对象将变得不可使用,并从缓存中移动出来。试想这样一种情况,应用从一个 XML 文件中读出金融信息,而该文件又被定期地修改。应用的作用是利用从该文件读出的信息构 造一个图形对象以表示销售的情况。当应用读入文件时,它把数据插入缓存中,并记录下文 件的依赖关系。当文件发生修改时,应用使开始产生的缓存对象无效并从内存中移出已经无 用的数据,此后应用重新读入文件的数据,再把更新后的数据放入缓存,这样就完成了信息 的更新,并返回给最终用户。 6.2.2 实例 例子: 从一个 XML 中读出用户信息并显示在页面上,页面提供了两个按钮,一个为增加用户, 一个为刷新。我们在内存中建立了一个缓存对象“DataCache5”, 它与客户信息文件” custom1.xml”建立了依赖关系。当 custom1.xml 文件未发生变化时,我们按下“刷新”按钮, 可以看到信息是从缓存中读出的;当我们输入客户相应的资料,增加了一个客户以后,再按 下“刷新“按钮后,我们可以看到客户信息变成了从文件读出。 1.ASPX 源程序(performance\FormDataCache.aspx): sub LoadData1 '当缓存对象 DataCache5 有效时,从缓存中读出客户信息;无效时,从文件读出信息 dim dv1 as DataView dv1=Cache("DataCache5") if dv1 = Nothing dim ds as DataSet
dim fs as files dim sr as stream reade ds=New DataSet fs=New FileStream (Server. Map Path("custom1. xml"), FileMode Open, FileAccess. Read) sr=New StreamReader(fs) ds ReadXml(sr) fs. Close dvl=new Data View(ds. Tables(O)) Cache. Insert("Data Caches", dv l, New cachedependency Server MapPath("custom1. xml"))) IblMsg. text="数据从文件中读出. blms text="数据从缓存中读出. 绑定到 Data grid1对象 Data Grid1, datasource =dvl Data Grid 1. databindo end sub sub Page Load(s as object, e as eventargs) 加载页面时,从文件中读出客户信息 if Not isPost back LoadDatalo ub Add Btn Click(s as object, e as eventargs) 增加一个客户信息到文件中 dim fs as fileStream dim reader as stream Reader dim ds as dataSet dim drl as DataRow dim twl as Text writer if Not Page Is valid IblMsg. text="还有域未曾填充. DS=New DataSet FS=New File Stream(Server. mappath("customl xml"), FileMode Open, FileAccess. Read, FileShare. ReadWrit Reac DS readxml( Reader) drl=DS. tables(0). newrowO drl("CustName")=txtName text drl("Custldno")=txtldno text
dim fs as FileStream dim sr as StreamReader ds=New DataSet fs=New FileStream(Server.MapPath("custom1.xml"),FileMode.Open,FileAccess.Read) sr=New StreamReader(fs) ds.ReadXml(sr) fs.Close() dv1=new DataView(ds.Tables(0)) Cache.Insert("DataCache5",dv1,New cachedependency(Server.MapPath("custom1.xml"))) lblMsg.text="数据从文件中读出..." Else lblmsg.text="数据从缓存中读出..." end if '绑定到 DataGrid1 对象 DataGrid1.datasource = dv1 DataGrid1.databind() end sub sub Page_Load(s as object,e as eventargs) '加载页面时,从文件中读出客户信息 if Not IsPostBack LoadData1() end if end sub sub AddBtn_Click(s as object,e as eventargs) '增加一个客户信息到文件中 dim FS as FileStream dim Reader as StreamReader dim DS as DataSet dim dr1 as DataRow dim tw1 as TextWriter if Not Page.IsValid lblMsg.text="还有域未曾填充..." else DS=New DataSet() FS=New FileStream(Server.mappath("custom1.xml"),FileMode.Open,FileAccess.Read,FileShare.ReadWrit e) Reader=New StreamReader(FS) DS.readxml(Reader) FS.Close() dr1=DS.tables(0).newrow() dr1("CustName")=txtName.text dr1("CustIdno")=txtIdno.text
drl("CustCard")=txt Card text DS. tables(O) rows. add(drl) FileStream(Server. Map Path("custom1. xml"), FileMode Create, FileAccess. Read Write, FileShare Re d Write) twl=New Stream Writer(FS) twl=textwriter. synchronized(twl) DS. writexml(twl) twlclose( d if sub refreshBtn Click(s as object, e as eventargs) LoadDatalo end sub 数据缓冲实验 XML文件缓存测试 添加一个客户信息 td>姓名:
dr1("CustCard")=txtCard.text DS.tables(0).rows.add(dr1) FS=New FileStream(Server.MapPath("custom1.xml"),FileMode.Create,FileAccess.ReadWrite,FileShare.Re adWrite) tw1=New StreamWriter(FS) tw1=textwriter.synchronized(tw1) DS.writexml(tw1) tw1.close() LoadData1() end if end sub sub RefreshBtn_Click(s as object,e as eventargs) LoadData1() end sub 数据缓冲实验 XML 文件缓存测试 添加一个客户信息 姓 名:
td>身份证号: casp: label id=lblMsg runat=server / html 2.初始运行效果 初始时,应用空间中无“ DataCache”缓存对象,故文件从 custom.xml中读出客户信息 开始时为空,只显示了字段名
身份证号: 信用卡号: 2.初始运行效果 初始时,应用空间中无“DataCache”缓存对象,故文件从 custom1.xml 中读出客户信息, 开始时为空,只显示了字段名
每 口区 文件)编辑①)查看)收藏)工具①)帮助0 打印编 XML文件缓存测试 CustName Custard 添加一个客户信息 姓名 身份证号 信用卡号 增加」刷」 数据从文件中读出 包完成 3.当添加一个用户信息后,文件 custom1xm发生改变,导致“ DataCache5”对象无效, LoadDatal过程依然从文件 custom.xml中读取信息,并更新 DataCache5对象 口 文件①)编辑①)查看①)收藏8)工具①)帮助Q XML文件缓存测试 ame custine tcard 111 1111111 111 添加一个客户信息 姓名11 身份证号 信用卡号:1 增加|刷新 数据从文件中读出 完成 「本地 Intranet 4.由于 custom xml文件未曾发生改变,所以当按下“刷新“按钮后,信息却是从缓存对 象 Data Cach5中读出来
3.当添加一个用户信息后,文件 custom1.xml 发生改变,导致“DataCache5”对象无效, LoadData1 过程依然从文件 custom1.xml 中读取信息,并更新 DataCache5 对象。 4.由于 custom1.xml 文件未曾发生改变,所以当按下“刷新“按钮后,信息却是从缓存对 象 DataCach5 中读出来