for循环效率,怎么提高,求大神支招

JIAVB6 2019-01-08 12:37:52
引用了以下这段代码,但是在数据量较大时,处理起来几很慢
如UBOUND(TEMPDATE)的值有320万时

Public Function URLEncode(ByVal strParameter As String) As String
Dim S As String
Dim i As Double
Dim intValue As Integer
Dim TmpData() As Byte
S = ""
TmpData = StrConv(strParameter, vbFromUnicode)
For i = 0 To UBound(TmpData)
intValue = TmpData(i)
If (intValue >= 48 And intValue <= 57) Or (intValue >= 65 And intValue <= 90) Or (intValue >= 97 And intValue <= 122) Then
S = S & Chr(intValue)
ElseIf intValue = 32 Then
S = S & "+"
Else
S = S & "%" & Hex(intValue)
End If
Next i
URLEncode = S
End Function

...全文
1547 43 打赏 收藏 转发到动态 举报
写回复
用AI写文章
43 条回复
切换为时间正序
请发表友善的回复…
发表回复
灵仙羽圣(墨) 2019-01-14
  • 打赏
  • 举报
回复
引用 8 楼 脆皮大雪糕 的回复:
对于前面提出的第一个问题,其实对于你的转换无非256种可能性,却要做几百万次条件分支和hex运算,何不先预先产生这256个字节可能性的转换对照表,然后几百万次的运算就编程几百万次的查表,效率就会提高很多。 以下代码就是用这个思路做了个查表的方式,并且写一个新的转换函数,和你原来的函数进行测试比较。计时的单位是毫秒。在我这里,处理时间基本可以减半。如果去除新函数中的字符串拼接代码,仅仅是查表赋值,那么处理结果都在20毫秒以内。也就是说你的代码慢我给你提出的两个问题里耗时基本各占一半,我的这个代码已经能解决第一个问题,目前主要耗时都是字符串拼接了。 第二个问题,饭后再看。

Option Explicit
Private Declare Function GetTickCount Lib "kernel32" () As Long
Dim aryTranTable(255) As String

Private Sub Command1_Click()
    Dim strOut As String
    Dim strTest As String
    strTest = "这是一个测试字符串,包括汉字、数字123、字母abcABC和空格 "
    Dim i As Integer
    For i = 1 To 11 '将字符串进行2^11倍增
        strTest = strTest + strTest
    Next
    strOut = strOut & "测试字符串长度:" & vbTab & LenB(strTest) & vbCrLf
    
    Dim lngTicStart  As Long
    Dim strUrl1 As String, strUrl2 As String
    '分别调用两个函数进行数据处理,比较时间
    '原函数的调用
    lngTicStart = GetTickCount '计时开始
        strUrl1 = URLEncode(strTest)
    strOut = strOut & "原函数用时:      " & vbTab & GetTickCount - lngTicStart & vbCrLf
    '新函数的调用
    lngTicStart = GetTickCount '计时开始
        initTranTable
    strOut = strOut & "转换表初始化用时:" & vbTab & GetTickCount - lngTicStart & vbCrLf
    
    lngTicStart = GetTickCount '计时开始
        strUrl2 = URLEncode_quick(strTest)
    strOut = strOut & "新函数用时:      " & vbTab & GetTickCount - lngTicStart & vbCrLf
    
    strOut = strOut & "新旧函数输出比较:" & vbTab & (strUrl1 = strUrl2) & vbCrLf
     
    MsgBox strOut
    Debug.Print strOut
End Sub
'初始化转换表
Private Sub initTranTable()
    Dim i As Integer
    For i = 0 To 255
        If (i >= 48 And i <= 57) Or (i >= 65 And i <= 90) Or (i >= 97 And i <= 122) Then
            aryTranTable(i) = Chr(i)
        ElseIf i = 32 Then
            aryTranTable(i) = "+"
        Else
            aryTranTable(i) = "%" & Hex(i)
        End If
    Next
End Sub
Public Function URLEncode_quick(ByVal strParameter As String) As String
    Dim S As String
    Dim i As Long
    Dim intValue As Integer
    Dim TmpData() As Byte

    TmpData = StrConv(strParameter, vbFromUnicode)
    For i = 0 To UBound(TmpData)
        URLEncode_quick = URLEncode_quick & aryTranTable(TmpData(i)) '将几百万次运算转换成几百万次内存查表。
    Next i

End Function

Public Function URLEncode(ByVal strParameter As String) As String
    Dim S As String
    Dim i As Double
    Dim intValue As Integer
    Dim TmpData() As Byte
    S = ""
    TmpData = StrConv(strParameter, vbFromUnicode)
    For i = 0 To UBound(TmpData)
    intValue = TmpData(i)
    If (intValue >= 48 And intValue <= 57) Or (intValue >= 65 And intValue <= 90) Or (intValue >= 97 And intValue <= 122) Then
    S = S & Chr(intValue)
    ElseIf intValue = 32 Then
    S = S & "+"
    Else
    S = S & "%" & Hex(intValue)
    End If
    Next i
    URLEncode = S
End Function

 
我本机执行结果 测试字符串长度: 135168 原函数用时: 12062 转换表初始化用时: 0 新函数用时: 7547 新旧函数输出比较: True
这才是分析问题该有的思维方式~点赞
千面(●—●) 2019-01-13
  • 打赏
  • 举报
回复
用switch语句,行不行啊
Lpd_Reason 2019-01-11
  • 打赏
  • 举报
回复
For循环应该是最接近汇编的循环了,目前无法进一步改进。你的注意力应该放在循环体里面吧。
weixin_44489767 2019-01-11
  • 打赏
  • 举报
回复
厉害,请问哪里有下载源代码的地方?
JIAVB6 2019-01-10
  • 打赏
  • 举报
回复
引用 36 楼 脆皮大雪糕的回复:
哎,咋就结贴了呢。一直没空,这会儿才想来解决我所说的第二个问题,一看结贴都没兴致了
哈哈 谈谈无休止 不要停 不要停
皮皮涵 2019-01-10
  • 打赏
  • 举报
回复
把产量换成long型呀
daichangshun 2019-01-10
  • 打赏
  • 举报
回复
继续继续~~~
JIAVB6 2019-01-09
  • 打赏
  • 举报
回复
引用 10 楼 JIAVB6的回复:
[quote=引用 8 楼 脆皮大雪糕的回复:]对于前面提出的第一个问题,其实对于你的转换无非256种可能性,却要做几百万次条件分支和hex运算,何不先预先产生这256个字节可能性的转换对照表,然后几百万次的运算就编程几百万次的查表,效率就会提高很多。 以下代码就是用这个思路做了个查表的方式,并且写一个新的转换函数,和你原来的函数进行测试比较。计时的单位是毫秒。在我这里,处理时间基本可以减半。如果去除新函数中的字符串拼接代码,仅仅是查表赋值,那么处理结果都在20毫秒以内。也就是说你的代码慢我给你提出的两个问题里耗时基本各占一半,我的这个代码已经能解决第一个问题,目前主要耗时都是字符串拼接了。 第二个问题,饭后再看。

Option Explicit
Private Declare Function GetTickCount Lib "kernel32" () As Long
Dim aryTranTable(255) As String

Private Sub Command1_Click()
    Dim strOut As String
    Dim strTest As String
    strTest = "这是一个测试字符串,包括汉字、数字123、字母abcABC和空格 "
    Dim i As Integer
    For i = 1 To 11 '将字符串进行2^11倍增
        strTest = strTest + strTest
    Next
    strOut = strOut & "测试字符串长度:" & vbTab & LenB(strTest) & vbCrLf
    
    Dim lngTicStart  As Long
    Dim strUrl1 As String, strUrl2 As String
    '分别调用两个函数进行数据处理,比较时间
    '原函数的调用
    lngTicStart = GetTickCount '计时开始
        strUrl1 = URLEncode(strTest)
    strOut = strOut & "原函数用时:      " & vbTab & GetTickCount - lngTicStart & vbCrLf
    '新函数的调用
    lngTicStart = GetTickCount '计时开始
        initTranTable
    strOut = strOut & "转换表初始化用时:" & vbTab & GetTickCount - lngTicStart & vbCrLf
    
    lngTicStart = GetTickCount '计时开始
        strUrl2 = URLEncode_quick(strTest)
    strOut = strOut & "新函数用时:      " & vbTab & GetTickCount - lngTicStart & vbCrLf
    
    strOut = strOut & "新旧函数输出比较:" & vbTab & (strUrl1 = strUrl2) & vbCrLf
     
    MsgBox strOut
    Debug.Print strOut
End Sub
'初始化转换表
Private Sub initTranTable()
    Dim i As Integer
    For i = 0 To 255
        If (i >= 48 And i <= 57) Or (i >= 65 And i <= 90) Or (i >= 97 And i <= 122) Then
            aryTranTable(i) = Chr(i)
        ElseIf i = 32 Then
            aryTranTable(i) = "+"
        Else
            aryTranTable(i) = "%" & Hex(i)
        End If
    Next
End Sub
Public Function URLEncode_quick(ByVal strParameter As String) As String
    Dim S As String
    Dim i As Long
    Dim intValue As Integer
    Dim TmpData() As Byte

    TmpData = StrConv(strParameter, vbFromUnicode)
    For i = 0 To UBound(TmpData)
        URLEncode_quick = URLEncode_quick & aryTranTable(TmpData(i)) '将几百万次运算转换成几百万次内存查表。
    Next i

End Function

Public Function URLEncode(ByVal strParameter As String) As String
    Dim S As String
    Dim i As Double
    Dim intValue As Integer
    Dim TmpData() As Byte
    S = ""
    TmpData = StrConv(strParameter, vbFromUnicode)
    For i = 0 To UBound(TmpData)
    intValue = TmpData(i)
    If (intValue >= 48 And intValue <= 57) Or (intValue >= 65 And intValue <= 90) Or (intValue >= 97 And intValue <= 122) Then
    S = S & Chr(intValue)
    ElseIf intValue = 32 Then
    S = S & "+"
    Else
    S = S & "%" & Hex(intValue)
    End If
    Next i
    URLEncode = S
End Function

 
我本机执行结果 测试字符串长度: 135168 原函数用时: 12062 转换表初始化用时: 0 新函数用时: 7547 新旧函数输出比较: True
经过处理 目前UBOUND值为3104807,耗时4453。[/quote] 去掉doevents完成耗时875
JIAVB6 2019-01-09
  • 打赏
  • 举报
回复
引用 8 楼 脆皮大雪糕的回复:
对于前面提出的第一个问题,其实对于你的转换无非256种可能性,却要做几百万次条件分支和hex运算,何不先预先产生这256个字节可能性的转换对照表,然后几百万次的运算就编程几百万次的查表,效率就会提高很多。 以下代码就是用这个思路做了个查表的方式,并且写一个新的转换函数,和你原来的函数进行测试比较。计时的单位是毫秒。在我这里,处理时间基本可以减半。如果去除新函数中的字符串拼接代码,仅仅是查表赋值,那么处理结果都在20毫秒以内。也就是说你的代码慢我给你提出的两个问题里耗时基本各占一半,我的这个代码已经能解决第一个问题,目前主要耗时都是字符串拼接了。 第二个问题,饭后再看。

Option Explicit
Private Declare Function GetTickCount Lib "kernel32" () As Long
Dim aryTranTable(255) As String

Private Sub Command1_Click()
    Dim strOut As String
    Dim strTest As String
    strTest = "这是一个测试字符串,包括汉字、数字123、字母abcABC和空格 "
    Dim i As Integer
    For i = 1 To 11 '将字符串进行2^11倍增
        strTest = strTest + strTest
    Next
    strOut = strOut & "测试字符串长度:" & vbTab & LenB(strTest) & vbCrLf
    
    Dim lngTicStart  As Long
    Dim strUrl1 As String, strUrl2 As String
    '分别调用两个函数进行数据处理,比较时间
    '原函数的调用
    lngTicStart = GetTickCount '计时开始
        strUrl1 = URLEncode(strTest)
    strOut = strOut & "原函数用时:      " & vbTab & GetTickCount - lngTicStart & vbCrLf
    '新函数的调用
    lngTicStart = GetTickCount '计时开始
        initTranTable
    strOut = strOut & "转换表初始化用时:" & vbTab & GetTickCount - lngTicStart & vbCrLf
    
    lngTicStart = GetTickCount '计时开始
        strUrl2 = URLEncode_quick(strTest)
    strOut = strOut & "新函数用时:      " & vbTab & GetTickCount - lngTicStart & vbCrLf
    
    strOut = strOut & "新旧函数输出比较:" & vbTab & (strUrl1 = strUrl2) & vbCrLf
     
    MsgBox strOut
    Debug.Print strOut
End Sub
'初始化转换表
Private Sub initTranTable()
    Dim i As Integer
    For i = 0 To 255
        If (i >= 48 And i <= 57) Or (i >= 65 And i <= 90) Or (i >= 97 And i <= 122) Then
            aryTranTable(i) = Chr(i)
        ElseIf i = 32 Then
            aryTranTable(i) = "+"
        Else
            aryTranTable(i) = "%" & Hex(i)
        End If
    Next
End Sub
Public Function URLEncode_quick(ByVal strParameter As String) As String
    Dim S As String
    Dim i As Long
    Dim intValue As Integer
    Dim TmpData() As Byte

    TmpData = StrConv(strParameter, vbFromUnicode)
    For i = 0 To UBound(TmpData)
        URLEncode_quick = URLEncode_quick & aryTranTable(TmpData(i)) '将几百万次运算转换成几百万次内存查表。
    Next i

End Function

Public Function URLEncode(ByVal strParameter As String) As String
    Dim S As String
    Dim i As Double
    Dim intValue As Integer
    Dim TmpData() As Byte
    S = ""
    TmpData = StrConv(strParameter, vbFromUnicode)
    For i = 0 To UBound(TmpData)
    intValue = TmpData(i)
    If (intValue >= 48 And intValue <= 57) Or (intValue >= 65 And intValue <= 90) Or (intValue >= 97 And intValue <= 122) Then
    S = S & Chr(intValue)
    ElseIf intValue = 32 Then
    S = S & "+"
    Else
    S = S & "%" & Hex(intValue)
    End If
    Next i
    URLEncode = S
End Function

 
我本机执行结果 测试字符串长度: 135168 原函数用时: 12062 转换表初始化用时: 0 新函数用时: 7547 新旧函数输出比较: True
经过处理 目前UBOUND值为3104807,耗时4453。
卖水果的net 2019-01-09
  • 打赏
  • 举报
回复
拼接到 5000 个字符后,应该把这 5000 字符单独保存走,再 从 空字符串再拼接。 最后,把前面那么多的 5000 再拼在一起。
舉杯邀明月 2019-01-09
  • 打赏
  • 举报
回复
试了一下,全英文字符,结果是一样的。

用我在5楼说的修正后,也比你原始的代码快一些。
但速度比大雪糕的代码还是要慢一些。
真正要提速,可能只有用字节数组处理了。
舉杯邀明月 2019-01-09
  • 打赏
  • 举报
回复

突然发现,居然是Fase…………

然而想明白了:因为大雪糕的测试字符串中有“汉字”,当然不能用我的那个方法了。
我换成全英文的字符试试。
舉杯邀明月 2019-01-09
  • 打赏
  • 举报
回复
引用 16 楼 JIAVB6 的回复:
[quote=引用 15 楼 舉杯邀明月 的回复:]
[quote=引用 14 楼 JIAVB6 的回复:]
[quote=引用 12 楼 脆皮大雪糕的回复:][quote=引用 11 楼 JIAVB6 的回复:]
[quote=引用 10 楼 JIAVB6的回复:]
经过处理 目前UBOUND值为3104807,耗时4453。

去掉doevents完成耗时875[/quote]

觉得还能提高,用字节字符串先进行缓存,然后一段一段的转换成字符串再拼接起来。
字符串拼接的时候不断的在重新申请更大的内存空间,这个动作消耗太大。如果能大幅减少字符串拼接次数,速度还能提高。
你要的这个功能我觉得优化到50毫秒以内才算正常[/quote]
啊 这样的效果更好了!想想怎么改动了,好难呀[/quote]
300多万字符的,用“字符串连接”方式操作能不到1秒完成?
你的电脑是有多强劲啊…………
[/quote]
相当强劲,不用&,速度就快起来了[/quote]

不用 & ?
那且不就是我在5楼说的吗……“用字节数组处理编码”…………


另外,我先前测试了一下大雪糕的代码,
 其实我发现用我在5楼说的方法把你的代码简单修正,效果立竿见影!
 在IDE中运行几次都说明,实际比“_quick( )还要quick…………
JIAVB6 2019-01-09
  • 打赏
  • 举报
回复

按脆皮大雪糕思路再想想。。。。。
JIAVB6 2019-01-09
  • 打赏
  • 举报
回复
引用 15 楼 舉杯邀明月 的回复:
[quote=引用 14 楼 JIAVB6 的回复:]
[quote=引用 12 楼 脆皮大雪糕的回复:][quote=引用 11 楼 JIAVB6 的回复:]
[quote=引用 10 楼 JIAVB6的回复:]
经过处理 目前UBOUND值为3104807,耗时4453。

去掉doevents完成耗时875[/quote]

觉得还能提高,用字节字符串先进行缓存,然后一段一段的转换成字符串再拼接起来。
字符串拼接的时候不断的在重新申请更大的内存空间,这个动作消耗太大。如果能大幅减少字符串拼接次数,速度还能提高。
你要的这个功能我觉得优化到50毫秒以内才算正常[/quote]
啊 这样的效果更好了!想想怎么改动了,好难呀[/quote]
300多万字符的,用“字符串连接”方式操作能不到1秒完成?
你的电脑是有多强劲啊…………
[/quote]
相当强劲,不用&,速度就快起来了
舉杯邀明月 2019-01-09
  • 打赏
  • 举报
回复
引用 14 楼 JIAVB6 的回复:
[quote=引用 12 楼 脆皮大雪糕的回复:][quote=引用 11 楼 JIAVB6 的回复:]
[quote=引用 10 楼 JIAVB6的回复:]
经过处理 目前UBOUND值为3104807,耗时4453。

去掉doevents完成耗时875[/quote]

觉得还能提高,用字节字符串先进行缓存,然后一段一段的转换成字符串再拼接起来。
字符串拼接的时候不断的在重新申请更大的内存空间,这个动作消耗太大。如果能大幅减少字符串拼接次数,速度还能提高。
你要的这个功能我觉得优化到50毫秒以内才算正常[/quote]
啊 这样的效果更好了!想想怎么改动了,好难呀[/quote]
300多万字符的,用“字符串连接”方式操作能不到1秒完成?
你的电脑是有多强劲啊…………
脆皮大雪糕 2019-01-09
  • 打赏
  • 举报
回复
哎,咋就结贴了呢。一直没空,这会儿才想来解决我所说的第二个问题,一看结贴都没兴致了
JIAVB6 2019-01-09
  • 打赏
  • 举报
回复
引用 12 楼 脆皮大雪糕的回复:
[quote=引用 11 楼 JIAVB6 的回复:] [quote=引用 10 楼 JIAVB6的回复:] 经过处理 目前UBOUND值为3104807,耗时4453。
去掉doevents完成耗时875[/quote] 觉得还能提高,用字节字符串先进行缓存,然后一段一段的转换成字符串再拼接起来。 字符串拼接的时候不断的在重新申请更大的内存空间,这个动作消耗太大。如果能大幅减少字符串拼接次数,速度还能提高。 你要的这个功能我觉得优化到50毫秒以内才算正常[/quote] 啊 这样的效果更好了!想想怎么改动了,好难呀
JIAVB6 2019-01-09
  • 打赏
  • 举报
回复
啊 这样的效果更好了!想想怎么改动了,好难呀
程序之猿 2019-01-09
  • 打赏
  • 举报
回复
还是很牛掰的样子……
加载更多回复(23)

7,762

社区成员

发帖
与我相关
我的任务
社区描述
VB 基础类
社区管理员
  • VB基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧