Office中国论坛/Access中国论坛

标题: 拷贝字符串速度之对比: CopyMemory 与 动态字节数组 [打印本页]

作者: wang1999    时间: 2015-6-9 16:33
标题: 拷贝字符串速度之对比: CopyMemory 与 动态字节数组
好久没写代码了, 前几天有看到说VBA调用API很慢(CopyMemory), 我听了很费解, 也不好说明, 只好用数据说话.
所以做了个有趣的的测试.主要代码如下:
Public ShareInt16(7) As Integer     '整形, 128位, 2*08=16个字节
Private Function TestSink_TestFun2() As Long
    Dim varRet As Long, i As Long, strTmp As String, bytData() As Byte
    If mblnSkipRun = False Then
        '测试函数与代码放入此
        strTmp = "&H7FFFABCD"
        bytData = strTmp
    End If
End Function


Private Function TestSink_TestFun1() As Long
    Dim varRet As Long, i As Long, strTmp As String
    If mblnSkipRun = False Then
        '测试函数与代码放入此
        strTmp = "7FFFABCD"
        CopyMemory ShareInt16(0), ByVal StrPtr(strTmp), 16&
    End If
End Function



图片如下:

[attach]56570[/attach]


结论:
CopyMemory比 VBA的动态字节数组, 整整快了2倍多
调用CopyMemory真的很快(后台调用指令很少)


作者: tmtony    时间: 2015-6-9 16:35
赞一个!!
作者: 风中漫步    时间: 2015-6-9 16:44
少了"&h"当然更快{:soso_e120:}
作者: wang1999    时间: 2015-6-9 17:14
风中漫步 发表于 2015-6-9 16:44
少了"&h"当然更快

呵呵,多了一个32位, CPU多跑了一次.
16字节对比20字节差25%, 算一下一次还是 CopyMemory 快1.5倍

其实重点不在此, 我只是说明调用API得当, 速度照样杠杠的


作者: tmtony    时间: 2015-6-9 17:47
是的,用系统内置的 有时速度会快不少,不过,对有些用户,可能 对API有恐惧

另对你那个测试结果报告是如何做出来,我反而更感兴趣:)
作者: zpy2    时间: 2015-6-10 05:08
这好象没可比性,一个string,一个lnt,Api用指针引用会在排序比较快些,但复制会差不多,还要分配内存
作者: tmtony    时间: 2015-6-10 12:34
也贴一篇 有关CopyMemory的相关文章
[API] 【高级编程】VBA及VB中利用CopyMemory使用指针
http://www.office-cn.net/thread-120040-1-1.html
作者: wang1999    时间: 2015-6-11 18:26
再深入一点, 两个问题?
1, 为什么 abytData = strTmp 字节数组赋值要慢? 它慢在哪?
2, 为什么 CopyMemory 要快呢? 它快在哪?
再深入要把这个问题弄懂, 就要对COM有所了解. 我也是忘记得差不多了.

1.1 它慢在, VB要多创建一个数组:SafeArray(动态数组的创建, 这个过程比较麻烦, 申请内存,指令要多) 然后再是数据复制.

2.1, 虽然CopyMemory是API,在"kernel32.dll"库中, 但这个库, 从系统启动时, 已经加载在内存中, 你VB中引用时, 已经VB无需再次加载, windows不过内存中调用罢了.
2.2 当然 ShareInt16 是公共申明的静态数组, 也有这点原因



作者: wang1999    时间: 2015-6-11 18:30
今天又进行一个比较
MID语句 对 CopyMemory 哪个快
    If mblnSkipRun = False Then
        Mid(msTmp1, 1&, 4&) = msTmp2   
    End If

CopyMemory 要多一句
    If mblnSkipRun = False Then
        mlTmp = StrPtr(msTmp2)
        CopyMemory ByVal StrPtr(mlTmp), ByVal msTmp2, 8&
    End If
注意: 是 MID语句 不是 MID函数

为了更公平, 这次全是公共申明

作者: wang1999    时间: 2015-6-11 19:36
本帖最后由 wang1999 于 2015-6-11 19:54 编辑

代码改了一下:
Mid(msTmp1, 1&, 4&) = msTmp2

CopyMemory ByVal StrPtr(msTmp1), ByVal StrPtr(msTmp2), 8&

'初始化数据
Private Sub cmdInitialize_Click()
    msTmp1 = String(16, vbNullChar)
    msTmp2 = "abcdef12345"
End Sub


结果如下:

[attach]56587[/attach]

思考:
两者竟然一不分仲伯. 虽然两次取指针并复制 StrPtr
1.说明  StrPtr 只是一条简单LONG赋值, 速度是相当快
2.少两条指令复制, MID 应该要快呀?  原来 Variant (String) 这个是输入值, MID慢在这里了.
3. copymemory 则慢在 两条  StrPtr 复制, 所以综合2,3点 两者速度基本一致
所以:
在MID语句不方便使用的情况下, copymemory 与指针结合 可以作为VBA的一个操作语句, 在代码中随意使用, 有更多的灵活性, 且不仅不会牺牲性能.




作者: wang1999    时间: 2015-6-11 19:39
tmtony 发表于 2015-6-9 17:47
是的,用系统内置的 有时速度会快不少,不过,对有些用户,可能 对API有恐惧

另对你那个测试结果报告是 ...

其实我只是作了一个简单EXCEL模板, 还是只是手动把测试数据复制到EXCEL.

作者: wang1999    时间: 2015-6-11 19:45
至于VBA调用API的整个来龙去脉, 是怎么回事, 我还真不怎么清楚. 不知道老大们, 有没有文章 推荐看一下.

(应该是先检查DLL是否加载, 如果已经加载则通过函数指针直接调用,这个是我的想像,没有事实的依据){:soso_e144:}
作者: tmtony    时间: 2015-6-11 21:24
wang1999 发表于 2015-6-11 19:45
至于VBA调用API的整个来龙去脉, 是怎么回事, 我还真不怎么清楚. 不知道老大们, 有没有文章 推荐看一下.

...

CopyMemory 这篇 文章值得一看
http://www.office-cn.net/thread-120040-1-1.html
作者: ganlinlao    时间: 2015-6-11 22:08
又看到一个开始在vb里涉及指针。毫不夸张地说,越深入,痛苦指数与日俱增。
有三篇具有里程碑意义的文章,你可以百度一下:
1、阿国哥的vb里实现callAnyfuncttionPtr。这一篇文章实在是有点石破天惊。
2、vb用dispcallfunc调用纯c的dll或delphi(pascal)的dll。注:api的调用方式是无法调用纯c的dll或delphi的dll的。
3、一个大学生写的在vb里实现类的继承(里面几乎包括了vb的所有难点和亮点)

不要问我,我叫雷人,雷锋的亲戚,我什么都不懂。
作者: wang1999    时间: 2015-6-12 12:32
本帖最后由 wang1999 于 2015-6-12 12:47 编辑

比memcpy更快的内存拷贝, 这个也不错
http://www.cnblogs.com/GoodGoodW ... /10/15/1852251.html

总结编译后的复制有两种
小数据逐步赋值
大数据循环赋值




作者: wang1999    时间: 2015-6-12 12:41
ganlinlao 发表于 2015-6-11 22:08
又看到一个开始在vb里涉及指针。毫不夸张地说,越深入,痛苦指数与日俱增。
有三篇具有里程碑意义的文章, ...

里程碑意义?有点夸张了吧, 这几篇实用性也不大.

我觉得老大推荐的不错, 主要是分类总结得不错.
http://www.office-cn.net/thread-120040-1-1.html


不过谢谢你的推荐,
作者: zpy2    时间: 2015-6-13 04:51
ganlinlao 发表于 2015-6-11 22:08
又看到一个开始在vb里涉及指针。毫不夸张地说,越深入,痛苦指数与日俱增。
有三篇具有里程碑意义的文章, ...

有链接吗?特别那个大学生的类,很想了解下。
作者: wang1999    时间: 2015-6-13 15:04
zpy2 发表于 2015-6-13 04:51
有链接吗?特别那个大学生的类,很想了解下。

在vb里实现类的继承, 其实这个很简单:基本用Implements来实现, 如果你装有VB6的MSDN, 里面就有详细的示例(可惜我现在没装), 只不用得很少, 给人感觉很神秘

我几年前弄过,可惜实用性真不是很强, 除非你用VBA开发的类有父子关系, 如创建类似ado中recordset与field之间的关系

作者: wang1999    时间: 2015-6-13 15:12
本帖最后由 wang1999 于 2015-6-25 11:37 编辑

今天给出VB中拷贝字符串速度之对比.
1表示倍数, 代表时间基数条件:2字节数
语句:MID$, 1
语句:MID, API:copymemory,  2
运算符:=, 4(需要清除原字符内存,然后再创建字符)
字节数组:byte(), 6(需要创建动态数组SAFEARRAY,然后再创建数据)

2015-06-25, 补充

条件:52字节数,28个字符
语句set, copymemory 1 (copymemory 还比Lset稍快)
运算符:=, 1.5
语句:MID$, 3





作者: t小宝    时间: 2015-6-14 13:44
不错,学习了
作者: zpy2    时间: 2015-6-16 10:33
wang1999 发表于 2015-6-13 15:04
在vb里实现类的继承, 其实这个很简单:基本用Implements来实现, 如果你装有VB6的MSDN, 里面就有详细的示例 ...

implements 我用过,用抽象类 ,实现接口,同一个接口,可以派生不同的类,应该叫多态。在vb中一般用后期绑定,用抽象类后,可以,前期绑定抽象类。
implements在vba中没有。
vb中对父对象的属性,全部要重新封装的,.net的可以。
作者: ganlinlao    时间: 2015-6-17 18:02
我前面说的继承,当然不是指implements。如果是implements接口继承,那就谈不上是什么汇集了大部分vb难点了。
我说的继承是指父子继承。当然也能够实现vb函数重载。不过还是算了,不谈这话题,扯远了。
作者: wang1999    时间: 2015-6-23 16:07
本帖最后由 wang1999 于 2015-6-23 16:26 编辑

再补充 "=" VS  "LSET":
哪家强

结论如下:
'等号赋值
Private Sub CopyStringEqual()
    Dim s1 As String, s2 As String
    s1 = "123456"
    Debug.Print StrPtr(s1)
    s2 = "654321"
    s1 = s2
    Debug.Print StrPtr(s1)
End Sub
'Lset 赋值
Private Sub CopyStringLet()
    Dim s1 As String, s2 As String
    s1 = "123456"
    Debug.Print StrPtr(s1)
    s2 = "654321"
    LSet s1 = s2
    Debug.Print StrPtr(s1)
End Sub
还是说明一下
LSET的用法注意了,两边要相等,否则你试试 :0)


作者: wang1999    时间: 2015-7-4 11:28
本帖最后由 wang1999 于 2015-7-4 11:57 编辑

最近自己将自己常用的VB函数,准备将其一部分用C重写为API(方便于excel或access调用,这样不用重写或复制代码了)
在深入编写API过程中发现很多VB的技术内幕,可以说VB就是COM技术的集合。

现在也完全明白了调用DLL的API的本质:分为动态调用及静态调用

动态调用:使用 Declare 申明(VB后台实则调用LoadLibrary进行加载)
静态调用:使用MIDL编写的TLB静态引用(直接二进制)

两者速度经过测试(环境有严格要求)
1,函数:1千万次*2行代码=(16(函数初始)+6(代码)=22条汇编指令),单位:毫秒,文件已编译
2. CPU全开,断网,清空后台,CUP空闲100%

结果如下:
动态调用
94
静态调用
62。得出每条指令2.818181818(1千万次)(共22条汇编指令)
两者相差了32毫秒,这应该就是动态调用,多用的时间,LoadLibrary 应该约12条汇编指令(前提是DLL已经加载到当前进程)






欢迎光临 Office中国论坛/Access中国论坛 (http://www.office-cn.net/) Powered by Discuz! X3.3