如何增强ASP程序性能(2)

---摘自《天极网》
技巧6：聪明地使用Session对象
Session在繁忙站点上使用时有几个缺陷。繁忙的意思是：站点上每秒有上百的页面被请求，或者同时有上千的访问用户。这个技巧对于那些要求水平扩展强的站点非常重要，也就是指这些站点：它们利用多个服务器完成数据装载或者处理大量容错。对于小型站点，比如内部网Intranet，Session是非常值得提倡的。
再次重申，ASP自动地为每一个首次点击Web服务器的用户创建一个Session，每一个Session占有大约10KB的内存，生存期默认是20分钟。
使用Session最大的问题不是性能，而是扩展性，Session不能跨越多个Web服务器，一旦在一个服务器上创建了Session，它的数据就驻留在那里。这意味着，如果在Web上使用Session，你就得为每一个直接访问存放Session服务器的用户请求设计一个策略。这就是将用户“粘”在Web服务器上，术语“sticky sessions”就来源于此。如果Web服务器遇到障碍，“Stuck”用户就会丢失他们的Session状态，因为Session不保留在磁盘上。
执行粘性session的策略包括硬件与软件解决方式，比如windows2000高级服务器中的 Network Load Balancing 以及Cisco公司的Local Director，但换取这些要牺牲一定的扩展性。
Application对象也不能跨越服务器。如果需要在Web群中共享并更新Application数据，就需要使用后台数据库。然而，只读Application数据在Web群中仍然很有用。
许多对任务要求严格的站点都要设立至少2个Web服务器，所以在设计严格任务的应用程序时，就需要执行“sticky sessions”，或者简单地避免使用Session，同时也可以采取其他保存用户状态到独立Web服务器的管理技术。
如果不使用Session，一定要确认将它们关闭，这可以通过Internet服务管理器实现。如果决定使用Session，可以通过几种方法来最小化它们的影响。
可以将不需要Session的内容（比如帮助画面，访问者区域，等等）移动到关闭Session的独立ASP应用程序中。在基础页面上，可以给ASP一个指示，让它不需要使用Session。将下面的代码直接加入到ASP页面的头部：

    <% @EnableSessionState=False %>

使用这个指示的一个很好的解释是在框架结构中Session创建了一个有趣的问题。ASP确保在一个时刻只有一个来自Session的请求被执行，这就确保了如果浏览器为单个用户请求多个页面时，只有一个ASP请求在那时能够接受Session，如此就避免了存取Session对象时的多线程问题。很不幸，在框架结构中的所有页面将按照连续的顺序显示出来，一个接一个，而不是同时，所以用户为了看到整个框架必须要等很长时间。规则是：如果一定的框架页面没有使用Session，就一定要告诉ASP直接使用@EnableSessionState=False。
除了使用Session对象，还有许多其他管理会话状态的选择。对于小数量的状态（小于4KB），我们通常建议使用cookie、查询字符串变量以及表单隐藏域。对于象购物车一样的大数量数据，后台数据库是最合适的选择。
技巧7：将代码装入COM对象中
如果要编写很多VBScript或者JScript，为了提个性能，可以将代码编写成COM对象并且编译使用。编译代码基本上比解释性代码运行快许多，编译组件对象可通过“early binding”存取其他COM对象，这比在脚本中调用组件要有效。
这么做有许多优点：

- COM对象有益于从商业规则中独立出表达式规则
- COM对象使代码重用变为可能
- 许多开发者发现用VB，C＋＋或者Visual J＋＋编写程序，比ASP更容易调试

COM对象也有缺点，包括初始开发时间和对不同编程技巧的需要。注意将少量ASP代码做成COM对象组件不会有好处，反而可能导致性能的损失，从而失去了编译代码的优势。怎样组合使用ASP脚本和COM对象达到最佳性能是一个测试的问题。我们注意到微软公司已经大规模在Windows 2000/IIS 5.0上提高了脚本与ADO的性能，由此，随着IIS5.0版本的引进，减少了编译代码的性能优势。
技巧8：使用Option Explicit
要在ASP文件中使用Option Explicit定义，并且放置到ASP文件的头部，从而强迫开发者在使用前声明所有的变量。许多程序员都认为这在应用程序调试时非常有用，因为它避免了产生错误类型变量以及偶然创建新变量的可能。
也许更重要的是，声明的变量要大大快于非声明变量。
技巧9：拷贝经常使用的数据到脚本变量中
在ASP中存取COM对象时，应该拷贝经常使用的对象数据到脚本变量中，这样就减少了对COM对象的方法调用。这些调用要比存取脚本变量相对来说费时费力。当存取Collection和Dictionary对象时，使用这项技巧也减少了昂贵的查找操作。
通常，如果要不止一次地存取对象数据，就应将数据放入脚本变量中，对象数据主要也就是Request变量（表单和查询字符串变量）。比如，站点要传递一个叫做UserID的查询字符串变量，假设它将在一个特殊页面被引用12次，那么不需要调用Request（“UserID”）12次，只要在ASP页面的头部分配给UserID一个变量，然后在页面中使用它，这样做就节省了11次COM方法的调用。
实际中，存取COM属性或方法是很昂贵的，下面的例子展示了通用代码：
Foo.bar.blah.baz = Foo.bar.blah.qaz(1)
If Foo.bar.blah.zaq = Foo.bar.blah.abc Then ' ...
上面的代码执行后，发生以下事情：
1、变量Foo被当作全局对象
2、变量bar被当作Foo的一员
3、变量blah被当作Foo.bar的一员
4、变量qaz被当作Foo.bar.blah的一员
5、调用Foo.bar.blah.quaz(1)
6、再执行步骤1到3分解baz
7、分解baz做为Foo.bar.blah的一员
8、再执行步骤1到3分解zaq
9、再执行步骤1到3一次分解abc
如上所示，这非常没有效率并且很慢。更快的方法是用VBScript编写代码，如下：
Set myobj = Foo.bar.blah ' do the resolution of blah ONCE
Myobj.baz = myobj.qaz(1)
If Myobj.zaq = Myobj.abc Then '...
如果使用VBScript 5.0或者更高版本，可以用With语句编写：

    With Foo.bar.blah
     .baz = .qaz(1)
     If .zaq = .abc Then '...
     ...
    End With

注意：这个技巧也可以应用在VB编程中。
技巧10：避免再定义数组
争取不要再定义数组。考虑到性能问题，如果机器的物理内存大小不够，最好按最差情况或者最佳情况设置数组的初始尺寸，需要时再重新定义。
下面的代码展示了Dim和Redim的使用：
< %
Dim MyArray()
Redim MyArray(2)
MyArray(0) = "hello"
MyArray(1) = "good-bye"
MyArray(2) = "farewell"
...
' some other code where you end up needing more space happens, then ...
Redim Preserve MyArray(5)
MyArray(3) = "more stuff"
MyArray(4) = "even more stuff"
MyArray(5) = "yet more stuff"
% >
简单地定义数组初始尺寸为合适的大小是非常好的，而不要用Redim加大数组。这么做也许浪费了一些内存（如果没有完全地使用空间），但是赢得了速度。