扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
静态变量慢于动态变量
在过程中引用静态局部变量要比引用常规局部动态变量慢2-3倍。要想真正地加速过程的执行速度,最彻底的方法就是将所有的静态变量转换为模块级别变量。
这种方法的唯一不足是:过程很少是自包含的,如果要在其他工程中重用,就必须同时拷贝并粘贴这些模块级别变量。
另外的一种处理方法是:在时间要求高的循环前,将静态变量数值装入动态变量中。
善用"Assume No Aliasing"编译选项
据说,如果过程能够2次或多次引用同样的内存地址,那么过程就会包含别名数值。一个典型的例子如下:
Dim g_GlobalVariable As Long
...
Sub ProcWithAliases(x As Long)
x = x + 1
g_GlobalVariable = g_GlobalVariable + 1
End Sub
如果传递给这个过程g_GlobalVariable变量,则将通过一个直接引用以及x参数两种方式修改变量的数值2次。
别名数值经常是不良编程习惯的产物,对于程序优化有害无益。事实上,如果能够完全确认应用程序从来没有使用到别名变量,就可以打开"Assume No Aliasing"高级编译选项,这将告知编译器没有过程可以修改同一内存地址,使编译器产生更加有效率的汇编代码。更特别的是,编译程序将试图缓冲这些数据到CPU的寄存器中,从而明显地加速了程序运行。
总结一下,当遇到以下情况时,就不会有别名数值:(1) 过程不引用任何全局变量 (2) 过程引用了全局变量,但从来不通过ByRef参数类型传递同一变量给过程 (3) 过程含有多个ByRef参数类型,但从来不传递同一变量到其中的2个或者多个之中。
你真正理解"Allow Unrounded Floating Point Operations"选项的含义吗?
来自微软的资料鼓吹:高级优化对话框中的所有编译选项都被认为是不稳定的,它们可能导致不正确的结果,甚至程序崩溃。对于其中的大多数,这种说法是正确的,但是经常有一个叫做"Allow Unrounded Floating Point Operations"的选项能够给予正确的结果,防止应用程序产生bug。考虑下面的代码段:
Dim x As Double, y As Double, i As Integer
x = 10 ^ 18
y = x + 1 ’ this can’t be expressed with 64 bits
MsgBox (y = x) ’ 显示 "True" (不正确的结果)
严格地说,由于X和Y变量不包含相同的数值,MsgBox将显示False。可问题是,由于数值1E18与1E18+1都以相同的64位浮点Double类型来表示,它们最终包含了几乎相同的数值,最后的MsgBox结果将是True。
如果打开了"Allow Unrounded Floating Point Operations"编译选项,VB就能重用已在数学协处理器堆栈中的数值,而不是内存中的数值(比如:变量)。因为FPU堆栈具备80位的精度,因此就可以区分出这2个数值的不同:
’ if the program is compiled using the
’ "Allow Unrounded Floating Point Operations" compiler option
MsgBox (y = x) ’ 显示 "False" (正确的结果)
总结一下:当以解释模式、或者编译的p-code模式、或者编译的native代码模式但关掉"Allow Unrounded Floating Point Operations"选项这3种方式运行一个程序时,所有浮点数字运算在内部都以80位的精度进行处理。但如果有一个数值是存储在64位Double变量中,结果就是接近的了,并且,随后使用那个变量的表达式也将产生近似的结果,而不是绝对正确的结果。
相反,如果打开"Allow Unrounded Floating Point Operations"编译选项后运行一段native编译代码,在随后的表达式中VB就经常能重用内部的80位数值,而忽略存储在变量中的当前数值。注意:我们并不能完全控制这个功能,VB也许对此生效,也许就不生效,这要取决于表达式的复杂程度以及最初分配数值语句与随后产生结果的表达式语句的距离远近。
除法运算符"\"与"/"的区别
整数间执行除法运算时,要使用 "\" 而不是 "/"。 "/" 运算符要求返回一个单一数值,所以,表面上看似简单的一行代码:
C% = A% / B%
实际上包含了3个隐含的转换操作:2个为除法运算做准备,从Integer转换到Single;一个完成最后的赋值操作,从Integer转换到Single。但是如果使用了"\"操作符,情况就大不相同了!不仅不会有这么多中间步骤,而且执行速度大大提高。
同时请记住:使用"/"操作符做除法运算时,如果其中之一是Double类型,那么结果就将是Double类型。所以,当2个Integer或者Single类型数值做除法运算时,如果想得到高精度的结果,就需要手工强迫其中之一转换为Double类型:
’结果为 0.3333333
Print 1 / 3
’结果为 0,333333333333333
Print 1 / 3#
使用"$-类型"字符串函数会更快
VB官方文档似乎很鼓励使用"无$"类字符串函数,比如:Left、LTrim或者UCase,而不是实现同样功能的Left$、LTrim$和UCase$函数。但是我们必须认识到:前者返回variant类型的数值,当用于字符串表达式中时,最终必须要转换为字符串(string)类型。
因此,在严格要求时间的代码段中,我们应该使用后者,它们将快5-10%。
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者