选择显示字体大小

改进 asp 的字符串处理性能

本文仅代表作者个人观点,正确与否请读者自行研究!

原文地址:http://www.microsoft.com/china/msdn/library/dnasp/html/aspstrcatn.asp

摘要:大多数 active server pages (asp) 应用程序都要通过字符串连接来创建呈现给用户的 html 格式的数据。本文对几种创建此 html 数据流的方法进行了比较,在特定情况下,某些方法在性能方面要优于其他方法。本文假定您已经具备一定的 asp 和 visual basic 编程方面的知识。

目录

简介

编写 asp 页面时,开发人员实际上是创建一个格式化的文本流,通过 asp 提供的 response 对象写入 web 客户端。创建此文本流的方法有多种,而您选择的方法将对 web 应用程序的性能和可缩放性产生很大影响。很多次,在我帮助客户优化其 web 应用程序的性能时,发现其中一个比较有效的方法是更改 html 流的创建方式。本文将介绍几种常用技术,并测试它们对一个简单的 asp 页面的性能所产生的影响。

asp 设计

许多 asp 开发人员都遵循良好的软件工程原则,尽可能地将其代码模块化。这种设计通常使用一些包含文件,这些文件中包含对页面的特定不连续部分进行格式化生成的函数。这些函数的字符串输出(通常是 html 表格代码)可以通过各种组合创建一个完整的页面。某些开发人员对此方法进行了改进,将这些 html 函数移到 visual basic com 组件中,希望充分利用已编译的代码提供的额外性能。

尽管这种设计方法很不错,但创建组成这些不连续 html 代码组件的字符串所使用的方法将对 web 站点的性能和可缩放性产生很大的影响,无论实际的操作是在 asp 包含文件中执行还是在 visual basic com 组件中执行。

字符串连接

请看以下 writehtml 函数的代码片断。名为 data 的参数只是一个字符串数组,其中包含一些要格式化为表格结构的数据(例如,从数据库返回的数据)。

function writehtml( data )dim nrepfor nrep = 0 to 99   shtml = shtml & vbcrlf _          & "<tr><td>" & (nrep + 1) & "</td><td>" _          & data( 0, nrep ) & "</td><td>" _          & data( 1, nrep ) & "</td><td>" _          & data( 2, nrep ) & "</td><td>" _          & data( 3, nrep ) & "</td><td>" _          & data( 4, nrep ) & "</td><td>" _          & data( 5, nrep ) & "</td></tr>"nextwritehtml = shtmlend function

这是很多 asp 和 visual basic 开发人员创建 html 代码时常用的方法。shtml 变量中包含的文本返回到调用代码,然后使用 response.write 写入客户端。当然,这还可以表示为直接嵌入不包含 writehtml 函数的页面的类似代码。此代码的问题是,asp 和 visual basic 使用的字符串数据类型(bstr 或 basic 字符串)实际上无法更改长度。这意味着每当字符串长度更改时,内存中字符串的原始表示形式都将遭到破坏,而且将创建一个包含新字符串数据的新的表示形式:这将增加分配内存和解除分配内存的操作。当然,asp 和 visual basic 已为您解决了这一问题,因此实际开销不会立即显现出来。分配内存和解除分配内存要求基本运行时代码解除各个专用锁定,因此需要大量开销。当字符串变得很大并且有大块内存要被快速连续地分配和解除分配时,此问题变得尤为明显,就像在大型字符串连接期间出现的情况一样。尽管这一问题对单用户环境的影响不大,但在服务器环境(例如,在 web 服务器上运行的 asp 应用程序)中,它将导致严重的性能和可缩放性问题。

下面,我们回到上述代码片段:此代码中要执行多少个字符串分配操作?答案是 16 个。在这种情况下,“&”运算符的每次应用都将导致变量 shtml 所指的字符串被破坏和重新创建。前面已经提到,字符串分配的开销很大,并且随着字符串的增大而增加,因此,我们可以对上述代码进行改进。

快捷的解决方案

有两种方法可以缓解字符串连接的影响,第一种方法是尝试减小要处理的字符串的大小,第二种方法是尝试减少执行字符串分配操作的数目。请参见下面所示的 writehtml 代码的修订版本。

function writehtml( data )dim nrepfor nrep = 0 to 99   shtml = shtml & ( vbcrlf _          & "<tr><td>" & (nrep + 1) & "</td><td>" _          & data( 0, nrep ) & "</td><td>" _                & data( 1, nrep ) & "</td><td>" _          & data( 2, nrep ) & "</td><td>" _          & data( 3, nrep ) & "</td><td>" _          & data( 4, nrep ) & "</td><td>" _          & data( 5, nrep ) & "</td></tr>" )nextwritehtml = shtmlend function

乍一看,可能很难发现这段代码与上一个代码示例的差别。其实,此代码只是在 shtml = shtml & 后的内容外面加上了括号。这实际上是通过更改优先顺序,来减小大多数字符串连接操作中处理的字符串大小。在最初的代码示例中,asp 编译器将查看等号右边的表达式,并从左到右进行计算。结果,每次重复都要进行 16 个连接操作,这些操作针对不断增长的 shtml 进行。在新版本中,我们提示编译器更改操作顺序。现在,它将按从左到右、从括号内到括号外的顺序计算表达式。此技术使得每次重复包括 15 个连接操作,这些操作针对的是不会增长的较小字符串,只有一个是针对不断增长的大的 shtml。图 1 显示了这种优化方法与标准连接方法在内存使用模式方面的比较。

图 1:标准连接与加括号连接在内存使用模式方面的比较

在特定情况下,使用括号可以对性能和可缩放性产生十分显著的影响,后文将对此进行进一步的说明。

stringbuilder

我们已经找到了解决字符串连接问题的快捷方法,在多数情况下,此方法可以达到性能和投入的最佳平衡。但是,如果要进一步提高构建大型字符串的性能,需要采用第二种方法,即减少字符串分配操作的数目。为此,需要使用 stringbuilder。stringbuilder 是一个类,用于维护可配置的字符串缓冲区,管理插入到此缓冲区的新文本片断,并仅在文本长度超出字符串缓冲区长度时对字符串进行重新分配。microsoft .net 框架免费提供了这样一个类 (system.text.stringbuilder),并建议在该环境下进行的所有字符串连接操作中使用它。在 asp 和传统的 visual basic 环境中,我们无法访问此类,因此需要自行创建。下面是使用 visual basic 6.0 创建的 stringbuilder 类示例(为简洁起见,省略了错误处理代码)。

option explicit' 默认的缓冲区初始大小和增长系数private const def_initialsize as long = 1000private const def_growth as long = 1000' 缓冲区大小和增长private m_ninitialsize as longprivate m_ngrowth as long' 缓冲区和缓冲区计数器private m_stext as stringprivate m_nsize as longprivate m_npos as longprivate sub class_initialize()   ' 设置大小和增长的默认值   m_ninitialsize = def_initialsize   m_ngrowth = def_growth   ' 初始化缓冲区   initbufferend sub' 设置初始大小和增长数量public sub init(byval initialsize as long, byval growth as long)   if initialsize > 0 then m_ninitialsize = initialsize   if growth > 0 then m_ngrowth = growthend sub' 初始化缓冲区private sub initbuffer()   m_nsize = -1   m_npos = 1end sub' 增大缓冲区private sub grow(optional minimimgrowth as long)   ' 初始化缓冲区(如有必要)   if m_nsize = -1 then      m_nsize = m_ninitialsize      m_stext = space$(m_ninitialsize)   else      ' 只是增长      dim ngrowth as long      ngrowth = iif(m_ngrowth > minimimgrowth,             m_ngrowth, minimimgrowth)      m_nsize = m_nsize + ngrowth      m_stext = m_stext & space$(ngrowth)   end ifend sub' 将缓冲区大小调整到当前使用的大小private sub shrink()   if m_nsize > m_npos then      m_nsize = m_npos - 1      m_stext = rtrim$(m_stext)   end ifend sub' 添加单个文本字符串private sub appendinternal(byval text as string)   if (m_npos + len(text)) > m_nsize then grow len(text)   mid$(m_stext, m_npos, len(text)) = text   m_npos = m_npos + len(text)end sub' 添加一些文本字符串public sub append(paramarray text())   dim narg as long   for narg = 0 to ubound(text)      appendinternal cstr(text(narg))   next nargend sub ' 返回当前字符串数据并调整缓冲区大小public function tostring() as string   if m_npos > 0 then      shrink      tostring = m_stext   else      tostring = ""   end ifend function' 清除缓冲区并重新初始化public sub clear()   initbufferend sub

此类中使用的基本原则是,在类级别将变量 (m_stext) 用作字符串缓冲区,并使用 space$ 函数以空格字符填充此缓冲区以将其设置为特定的大小。如果要将更多文本与现有文本连接在一起,则在检查缓冲区的大小足以存放新文本后,使用 mid$ 函数在正确位置插入文本。tostring 函数将返回当前存储在缓冲区中的文本,并将缓冲区的大小调整为能够容纳此文本的正确长度。使用 stringbuilderasp 代码如下所示:

function writehtml( data )dim osbdim nrepset osb = server.createobject( "stringbuildervb.stringbuilder" )' 用大小和增长系数初始化缓冲区osb.init 15000, 7500for nrep = 0 to 99   osb.append "<tr><td>", (nrep + 1), "</td><td>", _          data( 0, nrep ), "</td><td>", _          data( 1, nrep ), "</td><td>", _          data( 2, nrep ), "</td><td>", _          data( 3, nrep ), "</td><td>", _          data( 4, nrep ), "</td><td>", _          data( 5, nrep ), "</td></tr>"nextwritehtml = osb.tostring()set osb = nothingend function

使用 stringbuilder 需要一定的开销,因为每次使用此类时都必须创建它的实例,并且在创建第一个类实例时必须加载包含此类的 dll。对 stringbuilder 实例进行额外方法调用时也需要开销。使用加括号的“&”方法时,stringbuilder 如何执行取决于多个因素,包括连接的数目、要构建的字符串的大小以及选择的 stringbuilder 字符串缓冲区的初始化参数的性能。请注意,在多数情况下,将缓冲区中所需的空间量估计得略高一些要远远好于让其不断增长。

内置方法

asp 包含一种非常快捷的创建 html 代码的方法,只需多次调用 response.writewrite 函数使用隐式优化的字符串缓冲区,此缓冲区能够提供非常优秀的性能特性。修改后的 writehtml 代码如下所示:

function writehtml( data )dim nrepfor nrep = 0 to 99   response.write "<tr><td>"    response.write (nrep + 1)    response.write "</td><td>"   response.write data( 0, nrep )    response.write "</td><td>"   response.write data( 1, nrep )    response.write "</td><td>"    response.write data( 2, nrep )    response.write "</td><td>"   response.write data( 3, nrep )    response.write "</td><td>"   response.write data( 4, nrep )    response.write "</td><td>"   response.write data( 5, nrep )    response.write "</td></tr>"nextend function

虽然这段代码很可能为我们提供最佳的性能和可缩放性,但在某种程度上已经破坏了封装,因为现在会将函数内部的代码直接写入 response 流,所以调用代码丧失了一定程度的控制权。另外,移动此代码(例如,移入 com 组件)将变得更加困难,因为此函数与 response 流存在依赖关系。

测试

上面提到的四种方法分别通过一个简单的 asp 页面(包含一个由虚拟字符串数组提供数据的单个表格)进行了测试。我们使用 application center test&reg; (act) 从单个客户端(windows&reg; xp professional,piii-850mhz,512mb ram)针对 100mb/sec 网络中的单个服务器windows 2000 advanced server,双 piii-1000mhz,256mb ram)执行了测试。act 配置为使用 5 个线程,以模拟 5 个用户连接至网站时的负载。每个测试都包括 20 秒预热时间和随后的 100 秒负载时间,在负载期间创建了尽可能多的请求。

通过更改主表格循环中的重复次数,针对不同数目的连接操作重复运行测试,如 writehtml 函数中的代码片断所示。运行的每个测试都使用上文提到的四种不同的方法执行。

结果

下面的一系列图表显示了各种方法对整个应用程序吞吐量的影响,以及 asp 页面的响应时间。通过这些图表,我们可以了解应用程序支持的请求数目,以及用户等待页面下载至浏览器所需的时间。

表 1:使用的连接方法缩写的说明

方法缩写说明
resp内置 response.write 方法
cat标准连接(“&”)方法
pcat加括号的连接(“&”)方法
bldrstringbuilder 方法

在模拟典型 asp 应用程序工作负荷方面,此测试与实际情况相差甚远,从表 2 中可以明显看到,即使重复 420 次,此页面仍不是特别大。现在很多复杂的 asp 页面在这些数字上都是比较高的,设置有可能超出此测试范围的限制。

表 2:测试示例的页面大小和连接数目

重复次数连接数目页面大小(以字节为单位)
152402,667
304804,917
457207,167
609609,417
751,20011,667
1201,92018,539
1802,88027,899
2403,84037,259
3004,80046,619
3605,76055,979
4206,72062,219

图 2:吞吐量结果图

从图 2 的图表中可以看到,正如我们所预期的,多重 response.write 方法 (resp) 在测试的整个重复测试范围中为我们提供了最佳的吞吐量。但令人惊讶的是,标准字符串连接方法 (cat) 的下降如此巨大,而加括号的方法 (pcat) 在重复执行 300 多次时性能依旧要好很多。在大约重复 220 次之处,字符串缓存带来的性能提高超过了 stringbuilder 方法 (bldr) 固有的开销,在这一点以上,在此 asp 页面中使用 stringbuilder 所需的额外开销是值得的。

图 3:响应时间结果图

图 4:省略 cat 的响应时间结果图

图 3 和图 4 中的图表显示了按“到第一字节的时间”测量的响应时间(以毫秒为单位)。因为标准字符串连接方法 (cat) 的响应时间增加过快,所以又提供了未包括此方法的图表(图 4),以便分析其他方法之间的差异。有一点值得注意,多重 response.write 方法 (resp) 和 stringbuilder 方法 (bldr) 随重复次数的增加呈现一种近似线性的增长,而标准连接方法 (cat) 和加括号的方法 (pcat) 则在超过一定的阈值之后开始迅速增加。

小结

本文着重讲述了如何在 asp 环境中应用不同的字符串构建技术,这些内容同样适用于所有使用 visual basic 代码创建大型字符串的方案,例如手动创建 xml 文档。以下原则可以帮助您确定哪种方法最适合您的需要。

尽管您可能未看到本文所示的这种性能增长,但我已在真实的 asp web 应用程序中使用了这些技巧,只需要很少的额外投入就可以在性能和可缩放性方面获得很大的提高。

出处:microsoft
责任编辑:cjj

◎进入论坛网络编程版块参加讨论

相关文章 更多相关链接
[asp]利用 xmlhttp 分块上传文件
asp 中健壮的页结构的异常处理
asp 指南
asp编程入门进阶
ubb 转换函数演示
作者文章
改进 asp 的字符串处理性能
idea.com" method=get style="margin:0px; padding:0px;">idea.com">idea.com/img/google_search_title.gif;s:http://www.blueidea.com;forid:1;">
全网 idea.com';this.form.bisearch.value='cms';form.searchby.style.display='';document.getelementbyid('keyword').style.width='70px';">本站 idea.com';this.form.bisearch.value='bbs';form.searchby.style.display='none';document.getelementbyid('keyword').style.width='132px';">论坛
热门搜索:css fireworks 设计比赛 网页制作 dreamweaver studio8 flash
站点最新 站点最新列表
保持清晰的文档结构
月亮图腾教程ⅴ—最后一战
x-sapce使用系列教程
x-space安装系列教程
抽线以及虚线画法简明教程
创新设计 百万格子大楼
discuz!转换系列教程
世界杯足球的32个变种
易上手简单图层样式扣图
一封写给mm学习linux的信
栏目最新 栏目最新列表
保持清晰的文档结构
月亮图腾教程ⅴ—最后一战
x-sapce使用系列教程
x-space安装系列教程
抽线以及虚线画法简明教程
discuz!转换系列教程
易上手简单图层样式扣图
十分钟学会 xajax
css 菜单举一反三
利用照片制作版画简明教程

蓝色理想版权申明:除部分特别声明不要转载,或者授权我站独家播发的文章外,大家可以自由转载我站点的原创文章,但原作者和来自我站的链接必须保留(非我站原创的,按照原来自一节,自行链接)。文章版权归我站和作者共有。

转载要求:转载之图片、文件,链接请不要盗链到本站,且不准打上各自站点的水印,亦不能抹去我站点水印。

特别注意:本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

本文总共有 6 条评论,现在显示最新的 5 条。暂时没有人参于评分


218.18.49.177 publish at 2004-5-31 19:21:28
請問各位大俠, 在那裏可以找到用asp畫圖的組建啊 ----mschart.ocx
請聯係: tt
welunzhu@hotmail.com
221.237.53.50 publish at 2004-5-5 0:36:10
很早就看过英文原版了,还有那30个性能提升的文章。。。
218.72.35.51 publish at 2004-3-27 10:29:09
如对文章有意见,可以去论坛或在这里提出,不要留些无意义的话!谢谢合作!
61.146.128.66 publish at 2004-3-27 3:01:47
为何不让人家收藏
218.1.21.14 publish at 2004-3-25 12:00:34
很生动!

查看全部评论

asp" method="post" onsubmit="submit.disabled=true;">
您的评论
用户名:  口令:
说明:输入正确的用户名和密码才能参与评论。如果您不是本站会员,你可以注册 为本站会员。
注意:文章中的链接、内容等需要修改的错误,请用报告错误,以利文档及时修改。
不评分12345
注意:请不要在评论中含与内容无关的广告链接,违者封id
请您注意:
·不良评论请用报告管理员,以利管理员及时删除。
·尊重网上道德,遵守中华人民共和国的各项有关法律法规
·承担一切因您的行为而直接或间接导致的民事或刑事法律责任
·本站评论管理人员有权保留或删除其管辖评论中的任意内容
·您在本站发表的作品,本站有权在网站内转载或引用
·参与本评论即表明您已经阅读并接受上述条款
推荐文档 打印文档 评论文档 报告错误  
专业书推荐 更多内容
flash第一步系列》
《交互设计之路》
dreamweaver 从基础到实践》
《色彩管理》
网页设计专家门诊》
《情感化设计》
gui设计禁忌》
html>


 


关键字 本文所属关键字

相关 与本文相关文章

分类 所有文章关键字导航

源码编程相关

Java   Asp   PHP   .Net   XML   C/C++   CGI   VB   Jsp   J2ee   J2se   J2me   EJB   Servlet   Tomcat   Resin   Struts   Weblogic   Eclipse   ANT   GUI   JMS   Web servise   IDEA   Webphere   Hibernate   Spring   Jboss   Applet   Swing   Socket   Javamail   Perl   Ajax   P2P   安全   模式   框架   测试   开源   游戏

SQL数据库相关

My-SQL   Ms-SQL   Access   DB2   Oracle   Sybase   SQLserver   索引   存储过程   加密   数据库   分页   视图  

手机无线相关

3G   Wap   CDMA   GRPS   GSM   IVR   彩信   短信   无线   增值业务

网页设计制作相关

HTML   CSS   网页配色   网页特效   Javascript   VBscript   Dreamweaver   Frontpage   JS   Web   网站设计

网站建设推广相关

建站经验   网站优化   网站排名   推广   Alexa

操作系统/服务器相关

Windows XP   Windows 2000   Windows 2003   Windows Me   Windows 9.x   Linux   UNIX   注册表   操作系统   服务器   应用服务器

图形图像多媒体相关

Photoshop   Fireworks   Flash   Coreldraw   Illustrator   Freehand   Photoimpact   多媒体   图形图像

标准 网站致力的规范

Valid CSS!

无不良内容,无不良广告,无恶意代码

Valid XHTML 1.0 Transitional

creativecommons