前言
一提起VB/VBA,大家会想起什么?开发快速而方便,只是性能不咋地。VB/VBA太过陈旧,缺乏现代编程工具的很多特性,比如单一平台的深度依赖(不能跨平台),让人崩溃的多线程,几近残障的面向对象...这些妇孺皆知,让人耳熟能详的『特点』,似乎已深入人心。
然而,事实上真是这样么?按照微软的逻辑(详见《VB/VBA的解释器出来的那么早,为何没能跨平台?》),跨平台是系统的事,还轮不到VB/VBA来考虑,VB/VBA只需要舒服地躺在Windows即可。按照用户的逻辑,普罗大众会用非Windows?如若此,国产操作系统哪需要什么情怀来驱动!所以,跨平台这事,真跟VB/VBA扯不上半点关系。即便是跨平台的,到了Win的地界,不打点折扣能行?
多线程对于VB而言,有一个更安全,更折中的方案。当然对于其他语言的多线程,VB当然也行,就像指针一样,只不过诋毁不行的人,你用的是CopyMemory还是?至于VBA,多线程的方案则更成熟多样。
很多人说VB/VBA是基于对象而非面向对象,这种说法很让人迷惑。面向对象,是一套抽象的方法论,可以视为一种特殊的模板。二维的二进制要想拟合人类世界的千面万象,不分类那咋行?号称COM语言的VB/VBA,面向对象进行抽象,简直不能太方便啊!
剩下唯一可以批评VB/VBA的,大抵只有性能了。那么本篇,就结合案例,集中说下性能的事,或许VB/VBA会超出很多人的想象!
一、案例选择
在《变量,名不见经传里,竟还有这些秘密》《VB/VBA变量之居间行道!》中,BtOfficer就说变量体系对于任何一门语言,都是最锋利的,尤其是对于像C这样一类弱类型语言。VB/VBA也是弱类型的,BtOfficer也曾说,VB/VBA与VC的基座是一样的。既然如此,与变量体系有关,同时又能覆盖指针的使用,将是测试性能的不错选择。
那就来测试整数吧,将两个Integer类型(2字节有符号)的整数合并为1个Long类型(4字节有符号)整数,其中1个Integer整数代表Long类型的低字,另一个Integer整数代表Long类型的高字。
二、变量虽快,但变化之中难免困局,灵活性略显不足
VB/VBA中除了Byte类型外,其余都是有符号类型,很多人对此大为不满。因为有符号类型在整数表示上比无符号类型少了一半,但有符号类型胜在有负数,在应用中更贴近现实。所以,在VB/VBA中更注重实际需求,而且可表示的整数个数与无符号类型一样,并未因此而减少。更何况,VB/VBA中可用更大尺寸的整数来弥补有符号的不足。
变量驱动内存,在源码层,远比指针变量来得更方便和直接。所以很多时候,在VB/VBA中可以使用算术运算模拟很多VB/VBA中缺乏的特性,比如位运算,指针操作等。对于该测试,如果结果的Long类型是正数,也即高字为正数,那么可以用算术运算模拟如下:
测试下性能,因为算术运算的速度非常快,所以为了说明问题,每次测试重复调用该函数1000万次,并测试3次。测试函数如下(后续同):
结果为:765,873,890。没有对比,就没有伤害,所以性能如何暂不好说,且往下看。但是,HWord<0时,怎么用算术模拟呢?比如Get3201(-1,-2)。为了说明问题,使用NumBits函数查看Short类型的-1和-2的内存结构:
从测试过程可知,-1的内存结构为”11111111 11111111“,-2的内存结构为”11111111 11111110“,手工模拟的Long类型的内存结构为”11111111 11111110 11111111 11111111“,同样使用NumBits函数将其转换为Long类型整数为-65537。但是,如何将这两个2字节整数合并为4字节整数,使用算术模拟,确实不好办啊!这里就留个思考题给大家吧。
三、使用CopyMemory函数,操作便捷,但性能却不一定高
在VB/VBA中一提到指针,江湖上肯定忘不了CopyMemory函数,号称VB/VBA性能三板斧之一。VB/VBA是弱类型语言,通过操作内存来解决本篇的问题,非常的方便,如下图所示:
该函数的实现,充分利用了VB/VBA解释器/编译器,对内存的解释机制,仅需将相应的数据放到相应的内存即可。按上面的规矩,测试如下:
从测试过程来看,所谓的VB/VBA指针,虽然结果正确,但此处远没有利用变量来的高效。所以,编译器(解释器)及其优化要远比所谓的网传奇技淫巧有效!各位在使用各个编程工具时,要相信编译器,它远比很多个人大牛厉害得多。
所以,将CopyMemory函数视为VB/VBA指针的,是远远达不到C指针的效率的,VB/VBA指针也绝不是什么CopyMemory函数。
四、使用VB运行时自带的函数
脱离CopyMemory函数,还能否有其他更高效的方案呢?答案是有的,这便是VB运行库自带的一组导出函数(GetMemX和PutMemX),为使用方便,将其封装为IntPtr函数,使用该封装函数再来实现本篇测试项目,如下图所示:
注意,BtOfficer在早前的文章便说,函数名也是一个变量,上述函数就可以充分利用这一点,进一步提高性能。按上面的规矩,测试如下:
从测试结果来看,改进的实现基本上和变量的算术模拟运算的性能,相差无几。但这在某种程度上,可以替代CopyMemory函数,称为VB/VBA的指针么?
五、BtOfficer对VB/VBA运行时的扩展,具有更高性能
针对这一类问题,BtOfficer对VB/VBA的运行库进行了扩展,并以内置函数的方式体现为LngInts函数。按照前述测试规则,测试如下:
从测试结果来看,性能还是有非常显著的提升,竟然比CopyMemory快了近10倍左右。所以,这才是VB/VBA中指针应有的样子嘛!
欢迎关注BtOfficer(收藏、点赞、关注+转发),更多精彩仍在继续哦(扩展运行时将更系统,更全面,但需要阁下支持哦),有严肃的技术,也有轻松的唠嗑,期待你的加入!