1. 使用整数(Integer)和长整数(Long) 提高
代码运行速度最简单的
方法莫过于使用正确的数据类型了。也许你不相信,但是正确地选择数据类型可以大幅度提升
代码的
性能。在大多数情况下,程序员可以将Single,Double和Currency类型的变量替换为Integer或Long类型的变量,因为VB处理Integer和Long的能力远远高于处理其它几种数据类型。下面是排序: Long 最快 Integer . Byte . Single . Double . Currency 最慢 在大多数情况下,程序员选择使用Single或Double的原因是因为它们能够保存小数。但是小数也可以保存在Integer类型的变量中。例如程序中约定有三位小数,那么只需要将保存在Integer变量中的数值除以1000就可以得到结果。根据我的经验,使用Integer和Long替代Single,Double和Currency后,
代码的运行速度可以提高将近10倍。 2. 避免使用变体 对于一个VB程序员来说,这是再明显不过的事情了。变体类型的变量需要16个字节的空间来保存数据,而一个整数(Integer)只需要2个字节。通常使用变体类型的目的是为了减少设计的工作量和
代码量,也有的程序员图个省事而使用它。但是如果一个软件经过了严格设计和按照规范编码的话,完全可以避免使用变体类型。 在这里顺带提一句,对于Object对象也存在同样的问题。请看下面的
代码: Dim FSO Set FSO = New Scripting.FileSystemObject 或 Dim FSO as object Set FSO = New Scripting.FileSystemObject 上面的
代码由于在申明的时候没有指定数据类型,在赋值时将浪费内存和
cpu时间。正确的
代码应该象下面这样: Dim FSO as New FileSystemObject 3. 尽量避免使用
属性 在平时的
代码中,最常见的比较低效的
代码就是在可以使用变量的情况下,反复使用
属性(Property),尤其是在循环中。要知道存取变量的速度是存取
属性的速度的20倍左右。下面这段
代码是很多程序员在程序中会使用到的: Dim intCon as Integer For intCon = 0 to Ubound(SomVar()) Text1.Text = Text1.Text & vbcrlf & SomeVar(intCon) Next intCon 下面这段
代码的执行速度是上面
代码的20倍。 Dim intCon as Integer Dim sOutput as String For intCon = 0 to Ubound(SomeVar()) sOutput = sOutput & vbCrlf & SomeVar(intCon) Next Text1.Text = sOutput 同样地,像这样的
代码 . . . Do Until EOF(F) Line Input #F,nextLine Text1.Text = Text1.Text + nextLine Loop . . . 比下面的
代码慢得多: Do Until EOF(F) Line Input #F,nextLine bufferVar = bufferVar + nextLine Loop Text1.Text = bufferVar 然而,下面的
代码完成了相同的
功能,而且还要快: Text1.Text = Input(F,LOF(F)) 如上述,几种
方法都实现了同样的任务;同时,最好的算法也是最优的。 4. 尽量使用数组,避免使用集合 除非你必须使用集合(Collection),否则你应该尽量使用数组。据测试,数组的存取速度可以达到集合的100倍。这个数字听起来有点骇人听闻,但是如果你考虑到集合是一个对象,你就会明白为什么差异会这么大。 5. 展开小的循环体 在编码的时候,有可能遇到这种情况:一个循环体只会循环2到3次,而且循环体由几行
代码组成。在这种情况下,你可以把循环展开。原因是循环会占用额外的
cpu时间。但是如果循环比较复杂,你就没有必要这样做了。 6. 避免使用很短的
函数 和使用小的循环体相同,
调用只有几行
代码的
函数也是不经济的--
调用函数所花费的时间或许比执行
函数中的
代码需要更长的时间。在这种情况下,你可以把
函数中的
代码拷贝到原来
调用函数的地方。 7. 减少对子对象的引用 在VB中,通过使用.来实现对象的引用。例如: Form1.Text1.Text 在上面的例子中,程序引用了两个对象:Form1和Text1。利用这种
方法引用效率很低。但遗憾的是,没有办法可以避免它。程序员唯一可以做就是使用With或者将用另一个对象保存子对象(Text1)。 ' 使用With With frmMain.Text1 .Text = "Learn VB" .Alignment = 0 .Tag = "Its my life" .BackColor = vbBlack .ForeColor = vbWhite End With 或者 ' 使用另一个对象保存子对象 Dim txtText
Box as Text
Box Set txtText
Box = frmMain.Text1 TxtText
Box.Text = "Learn VB" TxtText
Box.Alignment = 0 TxtText
Box.Tag = "Its my life" TxtText
Box.BackColor = vbBlack TxtText
Box.ForeColor = vbWhite 注意,上面提到的
方法只适用于需要对一个对象的子对象进行操作的时候,下面这段
代码是不正确的: With Text1 .Text = "Learn VB" .Alignment = 0 .Tag = "Its my life" .BackColor = vbBlack .ForeColor = vbWhite End With 很不幸的是,我们常常可以在实际的
代码中发现类似于上面的
代码。这样做只会使
代码的执行速度更慢。原因是With块编译后会形成一个分枝,会
增加了额外的处理工作。 8. 检查字符串是否为空 大多数程序员在检查字符串是否为空时会使用下面的
方法: If Text1.Text = "" then ' 执行操作 End if 很不幸,进行字符串比较需要的处理量甚至比读取
属性还要大。因此我建议大家使用下面的
方法: If Len(Text1.Text) = 0 then ' 执行操作 End if 9.
去除Next关键字后的变量名 在Next关键字后
加上变量名会导致
代码的效率下降。我也不知道为什么会这样,只是一个经验而已。不过我想很少有程序员会这样画蛇添足,毕竟大多数程序员都是惜字如金的人。 '
错误的
代码 For iCount = 1 to 10 ' 执行操作 Next iCount ' 正确的
代码 For iCount = 1 to 10 ' 执行操作 Next 10. 使用数组,而不是多个变量 当你有多个保存类似数据的变量时,可以考虑将他们用一个数组代替。在VB中,数组是最高效的数据结构之一。 11. 使用动态数组,而不是静态数组 使用动态数组对
代码的执行速度不会产生太大的影响,但是在某些情况下可以节约大量的资源。 12. 销毁对象 无论编写的是什么软件,程序员都需要考虑在
用户决定终止软件运行后释放软件占用的内存空间。但遗憾的是很多程序员对这一点好像并不是很在意。正确的做法是在
退出程序前需要销毁程序中使用的对象。例如: Dim FSO as New FileSystemObject ' 执行操作 ' 销毁对象 Set FSO = Nothing 对于窗体,可以进行卸载: Unload frmMain 或 Set frmMain = Nothing 13. 变长和定长字符串 从技术上来说,与变长字符串相比,定长字符串需要较少的处理时间和空间。但是定长字符串的缺点在于在很多情况下,你都需要
调用Trim
函数以
去除字符串末的空字符,这样反而会降低
代码效率。所以除非是字符串的长度不会变化,否则还是使用变长字符串。 14. 使用类模块,而不是ActiveX控件 除非ActiveX控件涉及到
用户界面,否则尽量使用轻量的对象,例如类。这两者之间的效率有很大差异。 15. 使用内部对象 在涉及到使用ActiveX控件和DLL的时候,很多程序员喜欢将它们编译好,然后再加入工程中。我建议你最好不要这样做,因为从VB连接到一个外部对象需要耗费大量的
cpu处理能力。每当你
调用方法或存取
属性的时候,都会浪费大量的系统资源。如果你有ActiveX控件或DLL的源
代码,将它们作为工程的私有对象。 16. 减少模块的
数量 有些人喜欢将通用的
函数保存在模块中,对于这一点我表示赞同。但是在一个模块中只写上二三十行
代码就有些可笑了。如果你不是非常需要模块,尽量不要使用它。这样做的原因是因为只有在模块中的
函数或变量被
调用时,VB才将模块加载到内存中;当VB应用程序
退出时,才会从内存中卸载这些模块。如果
代码中只有一个模块,VB就只会进行一次加载操作,这样
代码的效率就得到了提高;反之如果
代码中有多个模块,VB会进行多次加载操作,
代码的效率会降低。 17. 使用对象数组 当设计
用户界面时,对于同样类型的控件,程序员应该尽量使用对象数组。你可以做一个实验:在窗口上
添加100个Picture
Box,每个Picture
Box都有不同的
名称,运行程序。然后创建一个新的工程,同样在窗口上
添加100个Picture
Box,不过这一次使用对象数组,运行程序,你可以注意到两个程序加载时间上的差别。 18. 使用Move
方法 在改变对象的位置时,有些程序员喜欢使用Width,Height,Top和Left
属性。例如: Image1.Width = 100 Image1.Height = 100 Image1.Top = 0 Image1.Left = 0 实际上这样做效率很低,因为程序
修改了四个
属性,而且每次
修改之后,窗口都会被重绘。正确的做法是使用Move
方法: Image1.Move 0,100,100 19. 减少
图片的使用
图片将占用大量内存,而且处理
图片也需要占用很多
cpu资源。在软件中,如果可能的话,可以考虑用背景色来替代
图片--当然这只是从技术人员的角度出发看这个问题。 20. 使用ActiveX DLL,而不是ActiveX控件 如果你设计的ActiveX对象不涉及到
用户界面,使用ActiveX DLL。 21. 使用类可以提高软件的整体
性能 VB提供的机制不完全
支持面向对象的设计和编码,但是VB提供了简单的类。大多数人认为使用对象将导致
代码的效率降低。对于这一点我个人有些不同的意见;考察
代码的效率不能纯粹从运行速度的角度出发,软件占用的资源也是需要考虑的因素之一。使用类可以帮助你在整体上提升软件的
性能。 22. 尽可能使用常数 使用常数可以加快应用程序的运行,增强
代码的可读性,而且易于维护。如果
代码中的字符串或数字是不变的,则可把它们声明为常数。常数在编译时只处理一次,将适当的值写进
代码;而变量在每次运行应用程序时都要读取当前值。 尽量使用对象浏览器中列举的内部常数,而不要自己去创建。不要担心应用程序中引用的模块包含多余的常数;多余的常数在形成 .exe
文件时被
删除。 23. 用 ByVal 传递参数,而不用 ByRef 编写含参数的 Sub 或 Function 过程时,按值 (ByVal) 传递参数比按地址 (ByRef) 快。尽管 Visual Basic 中参数传递的缺省方式是按地址的 (ByRef) ,但实际上需要改变参数值的过程极少。如果过程中不需改变参数的值,就可以按值 (ByVal) 来传递,举例说明如下: Private Sub DoSomething(ByVal strName As String,_ ByVal intAge As Integer) 24. 使用类型确定的可选参数 使用 Visual Basic 5.0 中类型确定的可选参数,可以提高 Sub 或 Function 的
调用速度。Visual Basic 以前版本中的可选参数只能是 Variant 的。如果过程是按值传递参数的,正如下面的例子,16 个字节的 Variant 变量保存在堆栈中。 Private Sub DoSomething(ByVal strName As String,_ Optional ByVal vntAge As Variant,_ Optional ByVal vntWeight As Variant) 使用类型确定的可选参数,每次
调用时占用的堆栈空间较少,而且传递到内存中的数据也较少: Private Sub DoSomething(ByVal strName As String,_ Optional ByVal intAge As Integer,_ Optional ByVal intWeight As Integer) 类型确定的可选参数的访问速度比 Variant 快,而且一旦数据类型
错误,编译时就
显示错误信息。 25利用集合的优点 可以定义和使用对象的集合是 Visual Basic 的强大
功能之一。尽管集合是非常有用的,但还要正确使用才能获得最好的
效果: 使用 For Each...Next 替代 For...Next。 26.
添加集合的对象时避免使用 Before 和 After 参数。 使用键集而不用几组相同对象的数组。 集合可以用 For...Next 循环进行迭代。但采用 For Each...Next 可读性更好,而且多数情况下更快。For Each...Next 是由集合的
生成器实现迭代的,所以实际的操作速度将随集合对象的不同而改变。由于 For Each...Next 的最简单的实现机理就是 For...Next 的线性迭代,因此 For Each...Next 不会比 For...Next 慢。但是,有些情况下采用了比线性迭代更复杂的实现机理,所以 For Each...Next 要快得多。 如果没有使用 Before 和 After 参数,则往集合中
添加对象是非常快的。否则,Visual Basic 必须在集合中检测到其它对象后,才能
添加新对象。 如果对象的类型都一样,集合或数组都可以用来管理这些对象(如果对象的类型不一样,则只能用集合)。从速度的观点看,选择何种方式取决于对象的访问方式。如果能够为每一对象分配唯一的键,则集合是访问对象的最快方式。使用键从集合中检索对象比从数组中顺序遍历对象快。当然,如果没有键而要遍历对象时,则选择数组比较好。就顺序遍历方式而言,数组比集合快。 如果对象的个数少,则数组使用的内存小,并且
搜索的速度快。当对象的个数在 100 左右时,集合比数组的效率高;当然,具体的数目还有赖于微处理器的速度和可用的内存。 26. 不要用Do While Not record.EOF 语句。 例如下面的
代码比较慢: Do While Not record.EOF '
代码 record.MoveNext Loop 下面的要快好多 Record.MoveLast intCount=Record.RecordCount Record.MoveFirst For i=1 To intCount '
代码 Records.MoveNext Next i 第二部分 编译优化 我所见过的很多VB程序员从来没有使用过编译选项,也没有试图搞清楚各个选项之间的差别。下面让我们来看一下各个选项的具体含义。 1. P-
代码(伪
代码)和本机
代码 你可以选择将软件编译为P-
代码或是本机
代码。缺省选项是本机
代码。那什么是P-
代码和本机
代码呢? P-
代码:当在VB中执行
代码时,VB首先是将
代码编译为P-
代码,然后再解释执行编译好的P-
代码。在编译环境下,使用这种
代码要比本机
代码快。选择P-
代码后,编译时VB将伪
代码放入一个EXE
文件中。 本机
代码:本机
代码是VB6以后才推出的选项。当编译为EXE
文件后,本机
代码的执行速度比P-
代码快。选择本机
代码后,编译时VB使用机器指令
生成EXE
文件。 在使用本机
代码进行编译时,我发现有时候会引入一些莫名其妙的
错误。在编译环境中我的
代码完全正确地被执行了,但是用本机
代码选项
生成的EXE
文件却不能正确执行。通常这种情况是在卸载窗口或弹出打印窗口时发生的。我通过在
代码中加入DoEvent语句
解决了这个问题。当然出现这种情况的几率非常少,也许有些VB程序员从来没有遇到过,但是它的确存在。 在本机
代码中还有几个选项: a)
代码速度优化:该选项可以编译出速度较快的执行
文件,但执行
文件比较大。推荐使用 b)
代码大小优化:该选项可以编译出比较小的执行
文件,但是以牺牲速度为代价的,不推荐使用。 c) 无优化:该选项只是将P-
代码转化为本机
代码,没有做任何优化。在调试
代码时可以使用。 d) 针对Pentium Pro优化:虽然该项不是本机
代码中的缺省选项,但是我通常会使用该选项。该选项编译出的可执行程序在Pentium Pro和Pentium 2以上的机器上可以运行得更快,而在比较老的机器上要稍稍慢一些。考虑到现在用Pentium 2都是落伍,所以推荐大家使用该选项。 e) 产生符号化调试信息:该项在编译过程中
生成一些调试信息,使
用户可以利用Visual C++一类的工具来调试编译好的
代码。使用该选项会
生成一个.pdf
文件,该
文件记录了可执行
文件中的标志信息。当程序拥有API
函数或DLL
调用时,该选项还是比较有帮助的。 2. 高级优化 高级优化中的设置可以帮助你提高软件的速度,但是有时候也会引入一些
错误,因此我建议大家尽量小心地使用它们。如果在
代码中有比较大的循环体或者复杂的数学运算时,选中高级优化中的某些项会大幅度提升
代码的
性能。如果你使用了高级优化
功能,我建议你严格测试编译好的
文件。 a) 假定无别名:可以提高循环体中
代码的执行效率,但是在如果通过变量的引用改变变量值的情况下,例如
调用一个
方法,变量的引用作为
方法的参数,在
方法中改变了变量的值的话,就会引发
错误。有可能只是返回的结果
错误,也有可能是导致程序中断运行的严重
错误。 b) 取消数组绑定检查、取消整数溢出检查和取消浮点
错误检查:在程序运行时,如果通过这些检查发现了
错误,
错误处理
代码会处理这些
错误。但是如果取消了这些检查,发生了
错误程序就无法处理。只有当你确定你的
代码中不会出现上面的这些
错误时,你才可以使用这些选项。它们将使软件的
性能得到很大的提升。 c) 允许不舍入的浮点操作:选择该选项可以是编译出来的程序更快地处理浮点操作。它唯一的缺点就是在比较两个浮点数时可能会导致不正确的结果。 d) 取消Pentium FDIV安全检查:该选项是针对一些老的Pentium芯片设置的,现在看来已经过时了。