Что нового

[Реестр] Чтение реестра - autoit против winapi

IMStrelcov

CTPEJIbLLOB
Сообщения
258
Репутация
66
почему в autoit встроеные функции для работы с реестром работают шустрее аналогичных функций на winapi,
а именно те что успел проверить до создания вопроса:

_WinAPI_RegSetValue
RegWrite

И

_WinAPI_RegQueryValue
RegRead

Каждую функцию запускал несколько раз в цикле на 1000 повторений операции, в итоге winapi раза в 3-и медленее.
так ка стандартные функции AutoIt немного корявы: например (приложение скомпилировано в х32, система х64), RegRead не может правильно считать данные из реестр типа QDWORD, через winapi считывает, но в 3-и раза медленее (при этом не завися от того какой тип данных считывать).

Кто что подскажет?
 

hedji

Продвинутый
Сообщения
409
Репутация
94
Autoit написан на C++, а _WinAPI реализованы через DllCall, т.е. как минимум время на подгрузку внешней dll.
 
Автор
IMStrelcov

IMStrelcov

CTPEJIbLLOB
Сообщения
258
Репутация
66
hedji сказал(а):
Autoit написан на C++, а _WinAPI реализованы через DllCall, т.е. как минимум время на подгрузку внешней dll.

Во первых dll открываю до цикла, а в цикле использою хендл открытой dll.
Во вторых сейчас вызвал функции в цикле по одному разу - разницы почти нет, а при цикле в два и более - разница существенна.
 

firex

AutoIT Гуру
Сообщения
943
Репутация
208
IMStrelcov
Возможно дело в DllCall, т.к. он при каждом вызове сканирует IMAGE_EXPORT_DIRECTORY, хотя я больше склоняюсь к тому, что у Вас неправильные сравнения.

Приведите пример.
 
Автор
IMStrelcov

IMStrelcov

CTPEJIbLLOB
Сообщения
258
Репутация
66
firex сказал(а):
IMStrelcov
Возможно дело в DllCall, т.к. он при каждом вызове сканирует IMAGE_EXPORT_DIRECTORY, хотя я больше склоняюсь к тому, что у Вас неправильные сравнения.

Приведите пример.

Код:
Global $Num = 10000

$time1 = TimerInit()
For $a=1 To $Num
   $result1 = RegRead('HKCU\AppEvents\EventLabels\.Default', 'DispFileName')
Next
$time1 = TimerDiff($time1)

Global $Dll = DllOpen('advapi32.dll')
Global $Hndl = advapi32_RegOpenKeyExW_('HKCU', 'AppEvents\EventLabels\.Default')

$time2 = TimerInit()
For $a=1 To $Num
   $result2 = advapi32_RegQueryValueExW_($Hndl, 'DispFileName')
Next
$time2 = TimerDiff($time2)

advapi32_RegCloseKey_($Hndl)
DllClose($Dll)

MsgBox(0,'','Время:'&@CRLF&'Autoit:'&@TAB&$time1&@CRLF&'WinApi:'&@TAB&$time2&@CRLF&@CRLF&'Результат:'&@CRLF&'Autoit:'&@TAB&$result1&@CRLF&'WinApi:'&@TAB&BinaryToString($result2, 2))

Func advapi32_RegQueryValueExW_($_Hndl, $_Key)
   Local $_Value, $_Size, $_Result
   While 1
	  $_Result = DllCall($Dll, 'long', 'RegQueryValueExW', 'handle', $_Hndl, 'wstr', $_Key, 'dword', 0, 'dword*', 0, 'struct*', $_Value, 'dword*', $_Size)
	  If @error Then
		 Return SetError(1, 0, 0)
	  EndIf
	  If $_Size Then
		 ExitLoop
	  ElseIf $_Result[6] Then
		 $_Value = DllStructCreate('byte['& $_Result[6]& ']');
		 $_Size = $_Result[6]
	  Else
		 Return SetError(2, 0, 0)
	  EndIf
   WEnd
   $_Value = DllStructGetData($_Value, 1)
    Return SetExtended($_Result[4], $_Value)
EndFunc

Func advapi32_RegOpenKeyExW_($_Section, $_SubSection = '', $_Access = 0x000F003F)
   Switch $_Section
	  Case 'HKLM', 'HKEY_LOCAL_MACHINE'
		 $_Section = 0x80000002
	  Case 'HKCU', 'HKEY_CURRENT_USER'
		 $_Section = 0x80000001
   EndSwitch
   Local $_Result = DllCall($Dll, 'long', 'RegOpenKeyExW', 'handle', $_Section, 'wstr', $_SubSection, 'dword', 0, 'dword', $_Access, 'ulong_ptr*', 0)
   If @error Then
	  Return SetError(1, 0, 0)
   ElseIf $_Result[0] Then
	  Return SetError(2, 0, 0)
   EndIf
   Return $_Result[5]
EndFunc

Func advapi32_RegCloseKey_($_Hndl)
   DllCall($Dll, 'long', 'RegCloseKey', 'handle', $_Hndl)
EndFunc


И да строка DllCall($Dll, 'long', 'RegQueryValueExW', 'handle', $_Hndl, 'wstr', $_Key, 'dword', 0, 'dword*', 0, 'struct*', $_Value, 'dword*', $_Size) у меня в цикле. Зачем? Первый раз получаем размер данных, а второй вызов получает уже сами данные и выходим из цикла.
Но дело в том что если функцию advapi32_RegQueryValueExW_() вызвать один раз (установить $Num = 1), то она даже выигрывает по скорости, а если параметр $Num = 10000, то выигрыш сразу пропадает. Зачем мне такие цифры? хочу реализовать снимок реестра, а там этих записей о-го-го.

Даже если DllCall($Dll, 'long', 'RegQueryValueExW', 'handle', $_Hndl, 'wstr', $_Key, 'dword', 0, 'dword*', 0, 'struct*', $_Value, 'dword*', $_Size) убрать из цикла и вызывать один раз, результат тот же.


Добавлено:
Сообщение автоматически объединено:

Проблема решена: проблема оказалась бональной.
Следовало изменить приоритет доступа в advapi32_RegOpenKeyExW_()
$_Access = 0x000F003F полный доступ
на
$_Access = 0x00020019 чтение

Увы проблема осталась, после перезагрузки системы все опять по старому.
 
Верх