前言:今天公司的老调查系统需要增加一个导出参与用户资料到.txt的功能。最多1个小时的工作,却进行了3个多小时,归其原因:一、公司网速太慢。更新 外网数据、测试、等待超过半个小时。二、程序代码未优化。程序执行时间超过90s直至超时(当时只导出了多一半用户,估计完整执行时间会超过180s), 被判不合格。最终找到原因在于字符串连接(好古老的问题)并通过优化执行时间降低到0.7s,速度提高100倍。
项目环境:ASP(VBScript)+MS SQLSERVER 2000+用户数据2600条
相信很多人都回使用下面的&字符串连接方式。仅列出开始时的主要代码:
程序写完后,本机测试通过(仅10个用户资料)。传到外网服务器上执行超时。开始以为什么地方处理的有问题,后来才发现连接字符串这里消耗太多的时间。于是开始寻求解决办法。
C#、VB6 中都有StringBuilder,ASP中应该如何处理呢?(后来找到MSDN,方知ASP中也可以调用StringBuilder)。通过GOOGLE找到了《改进 ASP 应用程序中的字符串处理性能 》-MSDN。于是按照 MSDN中的技巧通过使用() 括号将代码更改成如下:
运行,优化效果立刻显现出来执行时间 23s。
为什么增加“()”后就能这么明显的效率?MSDN中的解释是:“通过更改优先顺序,来减小大多数字符串连接操作中处理的字符串大小 。”
“在 最初的代码中,ASP 编译器将查看等号右边的表达式,并从左到右进行计算。结果,每次重复都要进行 29 个连接操作,这些操作针对不断增长的 OutputText 进行。在新版本中,我们提示编译器更改操作顺序。现在,它将按从左到右、从括号内到括号外的顺序计算表达式。此技术使得这些操作针对的是不会增长的较小字 符串,只有3个是针对不断增长的大的 OutputText。” 。
图 1:标准连接与加括号连接在内存使用模式方面的比较(来自MSDN中例子)
微软还给出了使用 StringBuilder 的优化方法。考虑到ASP中需要创建外部对象,而且微软例子中StringBuilder优化法对比“括号”技巧,对性能提高不明显,因此没有尝试使 用。(关于 StringBuilder 的性能可以参考 《改进ASP.....》一文)
23s的速度还是不能接受。根据上面的结果得知降低对大字符串的连接次数,能明显改善性能。因此继续在字符串连接上想办法:
可以看出代码增加了一个中间变量TempItemText用来连接每个用户资料,直接减少OutputText连接3倍。又通过 i 于 10取余数,大约每10个用户资料连接一次OutputText,再次减少10倍。Next后增加一个代码对最后可能的<10个用户的资料进行次 OutputText连接。总共优化15次OutputText连接。
至此在没有使用StringBuilder的情况下,将程序优化到0.7s,已能满足项目要求。
总结:一、利用表达式优先级减少对大字符串连接次数。(仅增加一对括号,对原代码的影响很少*推荐)
二、利用小字符串做中间变量减少对大字符串连接次数。
三、这个优化方法适用范围不局限在ASP中(C#等)。
文献参考:《改进 ASP 应用程序中的字符串处理性能 》