本帖最后由 pusofalse 于 2010-12-21 18:48 编辑  
 
对于没有特殊算法的问题,使用机器语言可能会稍快一些。新开了两个工作线程用于匹配子字符串,测试总用时35ms左右。只能用于32位系统,并且只能搜索纯文本Ansi数据,区分大小写。 
 
#include <Thread.au3>
Const $tagMATCH_STRING = "ptr BaseString;ptr SubString;dword SubStringLength"
Local $sFilePath, $hFile, $hSection, $pBaseAddress, $hThread
Local $pMatchStringA, $sSubString, $iLength, $tBuffer, $pBuffer, $iTimer
$sFilePath = "log.txt" ; 文件路径
$hFile = DllCall("Kernel32.dll", "handle", "CreateFile", "str", $sFilePath, _
                "dword", 0xC0000000, "dword", 3, "dword", 0, "dword", 3, _
                "dword", 0, "handle", 0)
$hFile = $hFile[0]
; 将文件映射至内存
$hSection = _RTCreateSection(0, $RT_SEC_COMMIT, $RT_PAGE_READWRITE, $RT_SECTION_ALL_ACCESS, 0, $hFile)
$pBaseAddress = _RTMapViewOfSection($hSection, $RT_SECTION_ALL_ACCESS)
$pMatchStringA = _MatchStringA()
; 子字符串
$sSubString1 = "F9F4F0F9F4F00000AA0000AA0000AA0000AA0000AA0000AA0000AA0000AA0000AA0000AA0000AA0000AAF9F4F00000AA"
$sSubString2 = "F9F4F0F9F4F0F9F4F0F9F4F0F9F4F0F9F4F0F9F4F0F9F4F0F9F4F0F9F4F0F9F4F0F9F4F0F9F4F0F9F4F0F9F4F0F9F4F0"
$iLength1 = StringLen($sSubString1)
$iLength2 = StringLen($sSubString2)
$pBuffer1 = _RTHeapAlloc(16 + $iLength1)
$tBuffer1 = DllStructCreate($tagMATCH_STRING, $pBuffer1)
DllStructSetData($tBuffer1, "BaseString", $pBaseAddress)
DllStructSetData($tBuffer1, "SubString", $pBuffer1 + 12)
DllStructSetData($tBuffer1, "SubStringLength", $iLength1)
_RTWriteBytes($pBuffer1 + 12, $sSubString1, "str", $iLength1)
$pBuffer2 = _RTHeapAlloc(16 + $iLength2)
$tBuffer2 = DllStructCreate($tagMATCH_STRING, $pBuffer2)
DllStructSetData($tBuffer2, "BaseString", $pBaseAddress)
DllStructSetData($tBuffer2, "SubString", $pBuffer2 + 12)
DllStructSetData($tBuffer2, "SubStringLength", $iLength2)
_RTWriteBytes($pBuffer2 + 12, $sSubString2, "str", $iLength2)
$iTimer = TimerInit()
; 创建工作线程。
$hThread1 = _RTCreateThread($pMatchStringA, $pBuffer1)
$hThread2 = _RTCreateThread($pMatchStringA, $pBuffer2)
; 等待匹配完成。
_RTWaitForObject($hThread1)
_RTWaitForObject($hThread2)
; 获取子串的数量。
$iCount1 = DllCall("Kernel32.dll", "bool", "GetExitCodeThread", "handle", $hThread1, "dword*", 0)
$iCount2 = DllCall("Kernel32.dll", "bool", "GetExitCodeThread", "handle", $hThread2, "dword*", 0)
MsgBox(0, $iCount1[2] & " " & $iCount2[2], TimerDiff($iTimer))
_RTHeapFree($pBuffer)
_RTCloseHandle($hFile)
_RTCloseHandle($hSection)
_RTCloseHandle($hThread1)
_RTCloseHandle($hThread2)
_RTUnmapViewOfSection($pBaseAddress)
Func _MatchStringA()
        Local Static $pStartAddr, $bCode, $pProcedures
        If $pStartAddr Then Return $pStartAddr
        $pStartAddr = _RTVirtualAlloc(1024)
        $pProcedures = $pStartAddr + 52
        $bCode = "0x" & _
                "55" & _                                        ; push        ebp
                "8BEC" & _                                        ; mov        ebp, esp
                "8B4508" & _                                        ; mov        eax, dword ptr [ebp+8]
                "85C0" & _                                        ; test        eax, eax
                "7423" & _                                        ; jz        $+23
                "56" & _                                        ; push        esi
                "8BF0" & _                                        ; mov        esi, eax
                "8B06" & _                                        ; mov        eax, dword ptr [esi]
                "57" & _                                        ; push        edi
                "33FF" & _                                        ; xor        edi, edi
                "FF7604" & _                                        ; push        dword ptr [esi+4]
                "50" & _                                        ; push        eax
                "FF15" & _RTLongPtrToBytes($pProcedures) & _        ; call        dword ptr [&strstr]
                "83C408" & _                                        ; add        esp, 8
                "85C0" & _                                        ; test        eax, eax
                "7406" & _                                        ; jz        $+6
                "47" & _                                        ; inc        edi
                "034608" & _                                        ; add        eax, dword ptr [esi+8]
                "EBE9" & _                                        ; jmp        $-17
                "8BC7" & _                                        ; mov        eax, edi
                "5F" & _                                        ; pop        edi
                "5E" & _                                        ; pop        esi
                "5D" & _                                        ; pop        ebp
                "C20400" & _                                        ; ret        4
                "909090" & _                                        ; nop
                _RTLongPtrToBytes(_RTGetProcAddress("msvcrt.dll", "strstr"))
        _RTInject($pStartAddr, $bCode)
        Return $pStartAddr
EndFunc        ;==>_MatchStringA
  
 
Thread.au3 - http://www.autoitx.com/forum.php ... p;page=1&extra= |