本帖最后由 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= |