Что нового

Создаём свой Au3Stripper на AutoIt

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Итак, я решил заняться гемо*ем... :laugh:

Прошу сюда писать тех, кто тесно сталкивался с Au3Stripper'ом и изучал его работу. А также тех, кто силён в парсинге строк.

На данном этапе интересует следующее:

* По какому принципу работают параметры в файле Au3Stripper.dat?
* Какой алгоритм лучше использовать для удаления неиспользуемых переменных?
* Какой алгоритм лучше использовать для удаления неиспользуемых функции?
* Что нужно учитывать при очистке?
* Нужны ли au3.api?

Всё вышесказанное, применимо к уже используемому алгоритму получение RAW кода, т.е на данный момент мне уже удалось превратить главный скрипт в один целый сливая все Includ'ы в один исходник, поэтому отталкиваться нужно уже с этой точки (хотя для оптимизации скорости конечно было бы лучше делать всё за один проход).

Заметки (в процессе изучения):
[Принципы стрипа]
* Для работы с массивами использовать Dictionary (должно быть быстрее).
* Первый этап - склеивание библиотек в один исходный код.
* При склеивании (по порядку):
- Склеивать обрывающиеся строки с «_» в одну.
- Удалять пустые строки, строки комментариев (включая блоки), пробелы в начале и в конце каждой строки.
- Удалять лишь следующие строки директив (начинающиеся с #): #pragma compile, #include-once, #include.
* Учитывать функцию в #OnAutoItStartRegister.
* Брать игнорируемые функции со всех директив #Au3Stripper_Ignore_Funcs/Vars, не только из той что в основном скрипте.
* Принципы удаления переменных:
- Претендуют на удаление только те переменные, которые имеют Global или Local в начале, а также те, которым не присваивается значение возвращаемое от обработки функции.
- Если объявлена локальная переменная с именем глобальной, то глобальная считается неиспользуемой.
- Если в перечни объявленных переменных найдена хоть одна используемая, то строка с объявлением не трогается.

[Принципы работы программы]
* Ini для указания путей (как приоритет). Для портативности.
* После Ini искать пути в папке верхнего уровня («..\», «..\..», «..\..\..»).
* В конце (если пути не найдены), искать в реестре («HKCU\Software\AutoIt v3\AutoIt\Include»).
* Сохранить те же параметры и директивы что и у Au3Stripper (для совместимости и лёгкой замены).
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
При очистке нужно ничего не трогать, я так считаю. Т.к. есть магия execute, eval, Assign итп и никогда не скажешь что переменная/функция не используется.
Можно лишь сделать предположение типа: Возможно функция __event_onReadyStateChange не используется, т.к нет прямых вызовов или переменных ссылающихся на нее.
Я лично не вижу большого смысла в этой проге. Ну сэкономишь ты 100 кб, а потом вставишь иконку на 250кб и вся экономия улетучилась.
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
inververs [?]
При очистке нужно ничего не трогать, я так считаю
Ну на это будут параметры. Но я же пытаюсь сделать аналог Au3Stripper, чтобы обойти некоторые его ограничения/недочёты.

Возможно функция __event_onReadyStateChange не используется, т.к нет прямых вызовов или переменных ссылающихся на нее.
Есть директива игнорирования.

Я лично не вижу большого смысла в этой проге. Ну сэкономишь ты 100 кб, а потом вставишь иконку на 250кб и вся экономия улетучилась.
Смысл есть, не только в уменьшении размера exe'шника, но и в скорости работы самой программы.
 

veretragna

Как писал, так и работает.
Сообщения
140
Репутация
10
Поддерживаю ответ CreatoR'a по поводу скорости работы скрипта, на англоязычном форуме умелец провел испытание со всеми флагами стриппера типа "/so /rm /pe" и наблюдал прирост в скорости от 5 до 30%.
Плюс я в собственных проектах заметил прирост.


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

CreatoR, в Au3Stripper.dat указаны сами проблемные функции, а также в каких по счету аргументах следует искать имена переменных и функций, а флаги означают тип искомых данных (0 - имя функции, 1 - имя переменной).
Пример:
Код:
adlibenable,1,0
означает, что искомое значение находится в первом аргументе, а тип искомых данных - имя функции.

Код:
hotkeyset,2,0
означает, что нужно проверять второй аргумент на имя функции.

Код:
isdeclared,1,1
означает, что нужно проверять первый аргумент на имя переменной.


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

За один проход оптимизировать не получится, т.к. нам в любом случае нужно использовать сквозной поиск по всем include'ам и самому скрипту, чтобы определить, используется ли вообще переменная/функция в коде или нет. Первым этапом однозначно будет создание одного цельного файла.

* Какой алгоритм лучше использовать для удаления неиспользуемых переменных/функций?
Однозначно сказать нельзя, т.к. нет вариантов подобных алгоритмов.

Я бы сделал ассоциативный массив с ключом "название переменной" и значением "счетчик упоминаний" (также можно записать, на какой строке ее объявили), прошелся бы по цельному файлу и записал, сколько раз упоминается переменная в коде. Только один раз - удаляем. То же по функциям.
Если упоминается 2 раза или более, можно и не трогать.

Как обычно, существует проблема с количеством проходов скрипта по тексту - для начала как минимум нужно составить список переменных, а вторым проходом чистить. И отдельно по функциям.


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

Тот же Au3Stripper проходит по скрипту 5 раз по умолчанию.
Объективных причин делать аж 5 итераций я не увидел, в первый же "большой проход" можно вырезать все лишнее.
Единственный случай, который приходит в голову, при котором нужно аж 5 итераций, это использование ключа /rm, когда скрипт 5 итераций подряд выбирает кратчайшие имена для для замены изначальных имен переменных и функций.


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

Что реально хотелось бы видеть - это вырезание неиспользуемых веток кода, например, если условие никогда не выполняется. Как это сделано в компиляторах С++. Но это уже трудная задача - высший пилотаж. (Предвидя вопросы: чтобы убирались, например, отладочные ветки кода из релиза).
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
veretragna [?]
означает, что искомое значение находится в первом аргументе, а тип искомых данных - имя функции.
означает, что нужно проверять первый аргумент на имя переменной.
Проверять на что?
Я вот не смог понять, если очищаются функции, а в этом параметре стоит 1 (проверять переменную), то он по переменной будет проверять имя функции, или для очистки функции это игнорируется?

Кстати Au3Stripper не до конца очищает функции и переменные...
Вот скрипт:
Код:
#include <WinAPI.au3>
#include <WinAPIFiles.au3>
ConsoleWrite(_WinAPI_GetFileTitle(@ScriptFullPath) & @LF)
MsgBox(64, @ScriptName, _WinAPI_GetClassName(WinGetHandle('')))


после обработки стрипера, остаются лишние переменные и функции:
Код:
Global Const $HGDI_ERROR = Ptr(-1)
Global Const $INVALID_HANDLE_VALUE = Ptr(-1)
Global Const $KF_EXTENDED = 0x0100
Global Const $KF_ALTDOWN = 0x2000
Global Const $KF_UP = 0x8000
Global Const $LLKHF_EXTENDED = BitShift($KF_EXTENDED, 8)
Global Const $LLKHF_ALTDOWN = BitShift($KF_ALTDOWN, 8)
Global Const $LLKHF_UP = BitShift($KF_UP, 8)
Global Const $tagRECT = "struct;long Left;long Top;long Right;long Bottom;endstruct"
Global Const $tagREBARBANDINFO = "uint cbSize;uint fMask;uint fStyle;dword clrFore;dword clrBack;ptr lpText;uint cch;" & "int iImage;hwnd hwndChild;uint cxMinChild;uint cyMinChild;uint cx;handle hbmBack;uint wID;uint cyChild;uint cyMaxChild;" & "uint cyIntegral;uint cxIdeal;lparam lParam;uint cxHeader" &((@OSVersion = "WIN_XP") ? "" : ";" & $tagRECT & ";uint uChevronState")
Func _WinAPI_GetClassName($hWnd)
If Not IsHWnd($hWnd) Then $hWnd = GUICtrlGetHandle($hWnd)
Local $aResult = DllCall("user32.dll", "int", "GetClassNameW", "hwnd", $hWnd, "wstr", "", "int", 4096)
If @error Or Not $aResult[0] Then Return SetError(@error, @extended, '')
Return SetExtended($aResult[0], $aResult[2])
EndFunc
Global Const $tagOSVERSIONINFO = 'struct;dword OSVersionInfoSize;dword MajorVersion;dword MinorVersion;dword BuildNumber;dword PlatformId;wchar CSDVersion[128];endstruct'
Global Const $__WINVER = __WINVER()
Func __WINVER()
Local $tOSVI = DllStructCreate($tagOSVERSIONINFO)
DllStructSetData($tOSVI, 1, DllStructGetSize($tOSVI))
Local $Ret = DllCall('kernel32.dll', 'bool', 'GetVersionExW', 'struct*', $tOSVI)
If @error Or Not $Ret[0] Then Return SetError(@error, @extended, 0)
Return BitOR(BitShift(DllStructGetData($tOSVI, 2), -8), DllStructGetData($tOSVI, 3))
EndFunc
Func _WinAPI_GetFileTitle($sFile)
Local $Ret = DllCall('comdlg32.dll', 'short', 'GetFileTitleW', 'wstr', $sFile, 'wstr', '', 'word', 4096)
If @error Or $Ret[0] Then Return SetError(@error, @extended, '')
Return $Ret[2]
EndFunc
ConsoleWrite(_WinAPI_GetFileTitle(@ScriptFullPath) & @LF)
MsgBox(64, @ScriptName, _WinAPI_GetClassName(WinGetHandle('')))


должно быть так:
Код:
Func _WinAPI_GetClassName($hWnd)
If Not IsHWnd($hWnd) Then $hWnd = GUICtrlGetHandle($hWnd)
Local $aResult = DllCall("user32.dll", "int", "GetClassNameW", "hwnd", $hWnd, "wstr", "", "int", 4096)
If @error Or Not $aResult[0] Then Return SetError(@error, @extended, '')
Return SetExtended($aResult[0], $aResult[2])
EndFunc
Func _WinAPI_GetFileTitle($sFile)
Local $Ret = DllCall('comdlg32.dll', 'short', 'GetFileTitleW', 'wstr', $sFile, 'wstr', '', 'word', 4096)
If @error Or $Ret[0] Then Return SetError(@error, @extended, '')
Return $Ret[2]
EndFunc
ConsoleWrite(_WinAPI_GetFileTitle(@ScriptFullPath) & @LF)
MsgBox(64, @ScriptName, _WinAPI_GetClassName(WinGetHandle('')))


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

Skif_off

Знающий
Сообщения
173
Репутация
12
CreatoR сказал(а):
Видимо переменные которым присвоено значение возвращаемое от функции, не очищаются, хотя и не используются.
Любопытно :smile: Т.е. можно спокойно выпилить вручную? Так было всегда, сколько пользуюсь, и всегда оставлял, комментарии разработчика не нашёл.
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Ещё кое что заметил - переменные, в которых используются другие переменные, тоже не выпиливаются, хотя и не используются.

В шапку добавил кое какие заметки.
 

veretragna

Как писал, так и работает.
Сообщения
140
Репутация
10
Проверять на что?

Поясняю свою мысль.
Все функции из списка Au3Stripper.dat принимают в качестве аргументов имена других функций или переменных. Вот, к примеру, HotKeySet во втором аргументе требует имя функции, которую нужно навешать на горячую клавишу, и при срабатывании клавиши вызывается указанная функция. То есть, кроме объявления, она как минимум используется в коде еще раз, а значит, вырезать ее не надо.

Au3Stripper согласно Au3Stripper.dat проверяет аргументы функций списка, чтобы отследить все упоминания функций/переменных в коде и не допустить вырезания лишнего кода.

Я вот не смог понять, если очищаются функции, а в этом параметре стоит 1 (проверять переменную), то он по переменной будет проверять имя функции, или для очистки функции это игнорируется?
Au3Stripper имеет список функций отдельно и список переменных отдельно (насколько я могу судить без исходного кода).
Понятно же, что второй аргумент HotKeySet нужно проверить именно по списку функций, а не переменных.
Если указать неправильный флаг, Stripper прогонит аргумент через неправильный список и получит неверный результат (что совпадений нет, например), и совершенно зря вырежет функцию, имя которой указано в аргументе.
Флаг не игнорируется ни в коем случае.


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

Идея насчет вырезания функций.
Если при первичном поиске функций, объявленных в скрипте, запоминать байт начала слова Func и конца слова EndFunc, вырезать ее потом будет очень просто. Достаточно в конце скопировать побайтово скрипт в другую переменную или другой файл, игнорируя эти участки.
Или заполнять их пробелами, а потом StringStripWS($..., 4).
В общем, идей валом.
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
veretragna [?]
Поддерживаю ответ CreatoR'a по поводу скорости работы скрипта, на англоязычном форуме умелец провел испытание со всеми флагами стриппера типа "/so /rm /pe" и наблюдал прирост в скорости от 5 до 30%.
можно подробнее по поводу скорости? я думал, что скорость работы кода зависит от самого кода.
да и ссылку не плохо бы на упомянутые тесты.
 

veretragna

Как писал, так и работает.
Сообщения
140
Репутация
10
Работа интерпретатора AutoIt (который в свою очередь написан на С++) базируется на построении и последующем выполнении т.н. "семантического дерева".
Если кратко, то чем короче имя переменной или функции, тем меньше времени тратится на ее вызов.
Идеально, если максимальный размер имени не больше 4 байт (2 символа юникода), тогда оно аккуратно помещается в регистр процессора (привет С++!) и передается по назначению еще быстрее. Иначе приходится ложить его в стек и скорость падает.
Конечно, наибольший прирост наблюдается в циклах.
Если вот эту конструкцию:
Код:
For $li In $ul
	$t_ActTrophies[0][0] += 1
	$t_ActTrophies[$t_ActTrophies[0][0]][0] = $li
Next

...сделать такой:
Код:
For $li In $ul
	$l[0][0] += 1
	$l[$l[0][0]][0] = $li
Next


..., интерпретатору на прокрутку такого цикла понадобится намного меньше времени, особенно на изначально длинных именах.

Сейчас поищу ссылку, выложу в тексте этого же сообщения.


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

Дополнено: ссылка.
Не совсем та, которую я в свое время видел, но тоже в тему.
Особенно рекомендую запустить длиннющий скрипт-пример со страницы, только что на моем ноуте разница между короткими и длинными именами составила больше 2 раз: 970 мс для длинных и 402 для коротких.
 

firex

AutoIT Гуру
Сообщения
943
Репутация
208
veretragna
Описанное вами вполне ожидаемо(сам так же думал), но тестами не подтверждается. В не зависимости от количества объявленных переменных и их длинны - скорость обращения к ним не меняется.

Экспериментировал даже с объявлением нескольких тысяч переменных с одинаковым префиксом и обращался к случайным.
Элементарно:
Код:
;$__1023_2046 = 1023
;$__501_1002 = 501

;#include <WinAPIEx.au3>
;For $i = 1 To 2000 Step 1
;	Assign('__' & $i & "_" & ( $i * 2 ), $i)
;Next

$iTime = TimerInit()
For $i = 1 To 50000 Step 1
	$__1023_2046 = $__501_1002
Next
MsgBox( 0, 0, TimerDiff($iTime))
 

veretragna

Как писал, так и работает.
Сообщения
140
Репутация
10
firex, будьте добры, запустите скрипт-пример из приведенной мною ссылки и сами увидите разницу =)
А впрочем, продублирую скрипт еще и тут.
Код:
Example1()
Example2()

Func Example1()
  Local $hTimer = TimerInit()
  Local $ThisIsAVeryLongNameForAnIntegerVariable00
  Local $ThisIsAVeryLongNameForAnIntegerVariable01
  Local $ThisIsAVeryLongNameForAnIntegerVariable02
  Local $ThisIsAVeryLongNameForAnIntegerVariable03
  Local $ThisIsAVeryLongNameForAnIntegerVariable04
  Local $ThisIsAVeryLongNameForAnIntegerVariable05
  Local $ThisIsAVeryLongNameForAnIntegerVariable06
  Local $ThisIsAVeryLongNameForAnIntegerVariable07
  Local $ThisIsAVeryLongNameForAnIntegerVariable08
  Local $ThisIsAVeryLongNameForAnIntegerVariable09
  Local $ThisIsAVeryLongNameForAnIntegerVariable10
  Local $ThisIsAVeryLongNameForAnIntegerVariable11
  Local $ThisIsAVeryLongNameForAnIntegerVariable12
  Local $ThisIsAVeryLongNameForAnIntegerVariable13
  Local $ThisIsAVeryLongNameForAnIntegerVariable14
  Local $ThisIsAVeryLongNameForAnIntegerVariable15
  Local $ThisIsAVeryLongNameForAnIntegerVariable16
  Local $ThisIsAVeryLongNameForAnIntegerVariable17
  Local $ThisIsAVeryLongNameForAnIntegerVariable18
  Local $ThisIsAVeryLongNameForAnIntegerVariable19
  Local $ThisIsAVeryLongNameForAnIntegerVariable20
  Local $ThisIsAVeryLongNameForAnIntegerVariable21
  Local $ThisIsAVeryLongNameForAnIntegerVariable22
  Local $ThisIsAVeryLongNameForAnIntegerVariable23
  Local $ThisIsAVeryLongNameForAnIntegerVariable24
  Local $ThisIsAVeryLongNameForAnIntegerVariable25
  Local $ThisIsAVeryLongNameForAnIntegerVariable26
  Local $ThisIsAVeryLongNameForAnIntegerVariable27
  Local $ThisIsAVeryLongNameForAnIntegerVariable28
  Local $ThisIsAVeryLongNameForAnIntegerVariable29
  Local $ThisIsAVeryLongNameForAnIntegerVariable30
  Local $ThisIsAVeryLongNameForAnIntegerVariable31
  Local $ThisIsAVeryLongNameForAnIntegerVariable32
  Local $ThisIsAVeryLongNameForAnIntegerVariable33
  Local $ThisIsAVeryLongNameForAnIntegerVariable34
  Local $ThisIsAVeryLongNameForAnIntegerVariable35
  Local $ThisIsAVeryLongNameForAnIntegerVariable36
  Local $ThisIsAVeryLongNameForAnIntegerVariable37
  Local $ThisIsAVeryLongNameForAnIntegerVariable38
  Local $ThisIsAVeryLongNameForAnIntegerVariable39
  Local $ThisIsAVeryLongNameForAnIntegerVariable40
  Local $ThisIsAVeryLongNameForAnIntegerVariable41
  Local $ThisIsAVeryLongNameForAnIntegerVariable42
  Local $ThisIsAVeryLongNameForAnIntegerVariable43
  Local $ThisIsAVeryLongNameForAnIntegerVariable44
  Local $ThisIsAVeryLongNameForAnIntegerVariable45
  Local $ThisIsAVeryLongNameForAnIntegerVariable46
  Local $ThisIsAVeryLongNameForAnIntegerVariable47
  Local $ThisIsAVeryLongNameForAnIntegerVariable48
  Local $ThisIsAVeryLongNameForAnIntegerVariable49
  Local $ThisIsAVeryLongNameForAnIntegerVariable50
  Local $ThisIsAVeryLongNameForAnIntegerVariable51
  Local $ThisIsAVeryLongNameForAnIntegerVariable52
  Local $ThisIsAVeryLongNameForAnIntegerVariable53
  Local $ThisIsAVeryLongNameForAnIntegerVariable54
  Local $ThisIsAVeryLongNameForAnIntegerVariable55
  Local $ThisIsAVeryLongNameForAnIntegerVariable56
  Local $ThisIsAVeryLongNameForAnIntegerVariable57
  Local $ThisIsAVeryLongNameForAnIntegerVariable58
  Local $ThisIsAVeryLongNameForAnIntegerVariable59
  Local $ThisIsAVeryLongNameForAnIntegerVariable60
  Local $ThisIsAVeryLongNameForAnIntegerVariable61
  Local $ThisIsAVeryLongNameForAnIntegerVariable62
  Local $ThisIsAVeryLongNameForAnIntegerVariable63
  Local $ThisIsAVeryLongNameForAnIntegerVariable64
  Local $ThisIsAVeryLongNameForAnIntegerVariable65
  Local $ThisIsAVeryLongNameForAnIntegerVariable66
  Local $ThisIsAVeryLongNameForAnIntegerVariable67
  Local $ThisIsAVeryLongNameForAnIntegerVariable68
  Local $ThisIsAVeryLongNameForAnIntegerVariable69
  Local $ThisIsAVeryLongNameForAnIntegerVariable70
  Local $ThisIsAVeryLongNameForAnIntegerVariable71
  Local $ThisIsAVeryLongNameForAnIntegerVariable72
  Local $ThisIsAVeryLongNameForAnIntegerVariable73
  Local $ThisIsAVeryLongNameForAnIntegerVariable74
  Local $ThisIsAVeryLongNameForAnIntegerVariable75
  Local $ThisIsAVeryLongNameForAnIntegerVariable76
  Local $ThisIsAVeryLongNameForAnIntegerVariable77
  Local $ThisIsAVeryLongNameForAnIntegerVariable78
  Local $ThisIsAVeryLongNameForAnIntegerVariable79
  Local $ThisIsAVeryLongNameForAnIntegerVariable80
  Local $ThisIsAVeryLongNameForAnIntegerVariable81
  Local $ThisIsAVeryLongNameForAnIntegerVariable82
  Local $ThisIsAVeryLongNameForAnIntegerVariable83
  Local $ThisIsAVeryLongNameForAnIntegerVariable84
  Local $ThisIsAVeryLongNameForAnIntegerVariable85
  Local $ThisIsAVeryLongNameForAnIntegerVariable86
  Local $ThisIsAVeryLongNameForAnIntegerVariable87
  Local $ThisIsAVeryLongNameForAnIntegerVariable88
  Local $ThisIsAVeryLongNameForAnIntegerVariable89
  Local $ThisIsAVeryLongNameForAnIntegerVariable90
  Local $ThisIsAVeryLongNameForAnIntegerVariable91
  Local $ThisIsAVeryLongNameForAnIntegerVariable92
  Local $ThisIsAVeryLongNameForAnIntegerVariable93
  Local $ThisIsAVeryLongNameForAnIntegerVariable94
  Local $ThisIsAVeryLongNameForAnIntegerVariable95
  Local $ThisIsAVeryLongNameForAnIntegerVariable96
  Local $ThisIsAVeryLongNameForAnIntegerVariable97
  Local $ThisIsAVeryLongNameForAnIntegerVariable98
  Local $ThisIsAVeryLongNameForAnIntegerVariable99

  For $i = 0 To 10000
    $ThisIsAVeryLongNameForAnIntegerVariable00 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable01 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable02 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable03 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable04 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable05 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable06 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable07 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable08 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable09 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable10 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable11 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable12 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable13 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable14 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable15 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable16 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable17 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable18 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable19 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable20 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable21 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable22 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable23 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable24 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable25 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable26 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable27 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable28 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable29 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable30 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable31 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable32 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable33 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable34 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable35 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable36 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable37 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable38 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable39 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable40 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable41 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable42 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable43 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable44 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable45 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable46 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable47 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable48 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable49 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable50 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable51 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable52 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable53 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable54 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable55 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable56 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable57 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable58 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable59 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable60 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable61 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable62 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable63 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable64 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable65 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable66 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable67 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable68 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable69 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable70 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable71 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable72 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable73 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable74 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable75 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable76 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable77 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable78 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable79 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable80 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable81 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable82 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable83 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable84 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable85 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable86 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable87 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable88 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable89 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable90 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable91 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable92 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable93 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable94 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable95 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable96 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable97 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable98 = $i
    $ThisIsAVeryLongNameForAnIntegerVariable99 = $i
  Next
  Local $iDiff = TimerDiff($hTimer)
  MsgBox(0, 0, "Time diff long variable names  = " & $iDiff & @CRLF )
EndFunc

Func Example2()
  Local $hTimer = TimerInit()
  Local $i00
  Local $i01
  Local $i02
  Local $i03
  Local $i04
  Local $i05
  Local $i06
  Local $i07
  Local $i08
  Local $i09
  Local $i10
  Local $i11
  Local $i12
  Local $i13
  Local $i14
  Local $i15
  Local $i16
  Local $i17
  Local $i18
  Local $i19
  Local $i20
  Local $i21
  Local $i22
  Local $i23
  Local $i24
  Local $i25
  Local $i26
  Local $i27
  Local $i28
  Local $i29
  Local $i30
  Local $i31
  Local $i32
  Local $i33
  Local $i34
  Local $i35
  Local $i36
  Local $i37
  Local $i38
  Local $i39
  Local $i40
  Local $i41
  Local $i42
  Local $i43
  Local $i44
  Local $i45
  Local $i46
  Local $i47
  Local $i48
  Local $i49
  Local $i50
  Local $i51
  Local $i52
  Local $i53
  Local $i54
  Local $i55
  Local $i56
  Local $i57
  Local $i58
  Local $i59
  Local $i60
  Local $i61
  Local $i62
  Local $i63
  Local $i64
  Local $i65
  Local $i66
  Local $i67
  Local $i68
  Local $i69
  Local $i70
  Local $i71
  Local $i72
  Local $i73
  Local $i74
  Local $i75
  Local $i76
  Local $i77
  Local $i78
  Local $i79
  Local $i80
  Local $i81
  Local $i82
  Local $i83
  Local $i84
  Local $i85
  Local $i86
  Local $i87
  Local $i88
  Local $i89
  Local $i90
  Local $i91
  Local $i92
  Local $i93
  Local $i94
  Local $i95
  Local $i96
  Local $i97
  Local $i98
  Local $i99

  For $i = 0 To 10000
    $i00 = $i
    $i01 = $i
    $i02 = $i
    $i03 = $i
    $i04 = $i
    $i05 = $i
    $i06 = $i
    $i07 = $i
    $i08 = $i
    $i09 = $i
    $i10 = $i
    $i11 = $i
    $i12 = $i
    $i13 = $i
    $i14 = $i
    $i15 = $i
    $i16 = $i
    $i17 = $i
    $i18 = $i
    $i19 = $i
    $i20 = $i
    $i21 = $i
    $i22 = $i
    $i23 = $i
    $i24 = $i
    $i25 = $i
    $i26 = $i
    $i27 = $i
    $i28 = $i
    $i29 = $i
    $i30 = $i
    $i31 = $i
    $i32 = $i
    $i33 = $i
    $i34 = $i
    $i35 = $i
    $i36 = $i
    $i37 = $i
    $i38 = $i
    $i39 = $i
    $i40 = $i
    $i41 = $i
    $i42 = $i
    $i43 = $i
    $i44 = $i
    $i45 = $i
    $i46 = $i
    $i47 = $i
    $i48 = $i
    $i49 = $i
    $i50 = $i
    $i51 = $i
    $i52 = $i
    $i53 = $i
    $i54 = $i
    $i55 = $i
    $i56 = $i
    $i57 = $i
    $i58 = $i
    $i59 = $i
    $i60 = $i
    $i61 = $i
    $i62 = $i
    $i63 = $i
    $i64 = $i
    $i65 = $i
    $i66 = $i
    $i67 = $i
    $i68 = $i
    $i69 = $i
    $i70 = $i
    $i71 = $i
    $i72 = $i
    $i73 = $i
    $i74 = $i
    $i75 = $i
    $i76 = $i
    $i77 = $i
    $i78 = $i
    $i79 = $i
    $i80 = $i
    $i81 = $i
    $i82 = $i
    $i83 = $i
    $i84 = $i
    $i85 = $i
    $i86 = $i
    $i87 = $i
    $i88 = $i
    $i89 = $i
    $i90 = $i
    $i91 = $i
    $i92 = $i
    $i93 = $i
    $i94 = $i
    $i95 = $i
    $i96 = $i
    $i97 = $i
    $i98 = $i
    $i99 = $i
  Next
  Local $iDiff = TimerDiff($hTimer)
  MsgBox(0, 0, "Time diff short variable names = " & $iDiff & @CRLF )
EndFunc
 

firex

AutoIT Гуру
Сообщения
943
Репутация
208
veretragna
Какое отношение имеет анализ кода к использованию переменных? Адекватные люди объявляют как можно больше переменных до основного цикла.
 

veretragna

Как писал, так и работает.
Сообщения
140
Репутация
10
firex, прошу Вас еще раз внимательно прочитать приведенный код.
Сначала в теле функции _Example* объявляются несколько десятков локальных переменных, а уже потом, в цикле, они используются.
Что не так?

UPD.
Мне кажется, или вот в этом участке кода
Код:
$__1023_2046 = $__501_1002

... вы используете одну и ту же пару переменных? Где Eval() или нечто подобное для использования разных переменных?
 

firex

AutoIT Гуру
Сообщения
943
Репутация
208
veretragna
Я не понятно с чего решил, что вы утверждаете о падении скорости при большом количестве объявленных переменных, зачитался... Так то очевидно, и касается это не только длинны переменных. Каждый анализ строки кода это затраты времени, а если они еще и длинные, так вообще отдельная история.
 

veretragna

Как писал, так и работает.
Сообщения
140
Репутация
10
firex, вот тут я с Вами абсолютно согласен.
На сем предлагаю и закончить спор, иначе в оффтопик уйдем.
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
протестил код. убрал циклы. только объявление переменных
временами код, где длинные переменные, показывал на порядок лучшие показатели
уберите циклы и протестите. я не понял почему такие расхождения
Ex1() - 0.202509009831994
Ex2() - 0.12409234734216
Ex1() - 0.20331742903292
Ex2() - 0.123688137741697
 

veretragna

Как писал, так и работает.
Сообщения
140
Репутация
10
Вот в этом примере наблюдается ожидаемая картина.
joiner, я предполагаю, что для точного измерения времени объявления переменных недостаточно всего лишь сотни штук. Может быть большой разброс времени из-за множества факторов, которые понижают точность.
А на выборке в 100 тысяч штук можно получить достоверный результат.

Код:
Example1()
Example2()

Func Example1()
	Local $hTimer = TimerInit()
	For $i = 1 to 100000
		Assign("ThisIsAVeryLongNameForAnIntegerVariable" & $i, 0)
	Next

	Local $iDiff = TimerDiff($hTimer)
	MsgBox(0, 0, "Time diff long variable names= " & $iDiff & @CRLF )
EndFunc

Func Example2()
	Local $hTimer = TimerInit()
	For $i = 1 to 100000
		Assign("l" & $i, 0)
	Next

	Local $iDiff = TimerDiff($hTimer)
	MsgBox(0, 0, "Time diff short variable names = " & $iDiff & @CRLF )
EndFunc


Преимущество коротких фраз, конечно, наблюдается не двукратное, но процентов 30-40 точно есть.
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
при запуске в редакторе "еще лучше" результаты
Ex1() - 0.209380573039866
Ex2() - 0.234441568268576
Ex1() - 0.216656345848202
Ex2() - 0.812461296930756
Ex1() - 0.220294232252369
Ex2() - 0.162492259386151
при замене порядка запуска функций, уже конкретно проигрывает , как и положено, функция с длинными именами.
при запуске одной и той же функции два раза подряд ( взял функцию с короткими именами) второй запуск выдает худшее время
не всегда. но регулярно


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

насчет функции замены имен переменных на максимально короткие то это класс. не знал что это влияет на скорость в циклах. (влияние незнания основ)
 
Автор
CreatoR

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
veretragna [?]
Прошу озвучить все :smile:.

Что касается точности проверки кусков кода, я обычно использую такой метод:

Код:
Global $iItrs = 100000

_SpeedTest('Test_AssignLong', 'Assign Long variable names')
_SpeedTest('Test_AssignShort', 'Assign Short variable names')
_SpeedTest('Test_ReadLong', 'Read Long variable names')
_SpeedTest('Test_ReadShort', 'Read Short variable names')

Func _SpeedTest($sTestFunc, $sTitle = 'Testing', $iRepeat_Test = 5)
	Local $aTests[$iRepeat_Test + 1] = [$iRepeat_Test]
	Local $iTotal_Tests = 0
	
	ConsoleWrite(StringFormat('+ Tests for "Func %s" (%s) started...\n=--------------------=\n', $sTestFunc, $sTitle))
	
	For $x = 1 To $iRepeat_Test
		$iTimer = TimerInit()
		
		;=== CODE TEST ====
		Call($sTestFunc)
		;=== CODE TEST ===
		
		$aTests[$x] = Round(TimerDiff($iTimer), 3)
		$iTotal_Tests += $aTests[$x]
		ConsoleWrite(StringFormat('- Test #%i: %.2f ms\n', $x, $aTests[$x]))
	Next
	
	Local $iAverage = Round($iTotal_Tests / $iRepeat_Test, 3)
	ConsoleWrite(StringFormat('======================\n! Tests average: %.2f ms\n\n', $iAverage))
EndFunc

Func Test_AssignLong()
   For $i = 0 To $iItrs
		Assign('ThisIsAVeryLongNameForAnIntegerVariable' & $i, 0)
	Next
EndFunc

Func Test_AssignShort()
	For $i = 0 To $iItrs
		Assign('l' & $i, 0)
	Next
EndFunc

Func Test_ReadLong()
	For $i = 0 To $iItrs
		Eval('ThisIsAVeryLongNameForAnIntegerVariable' & $i)
	Next
EndFunc

Func Test_ReadShort()
	For $i = 0 To $iItrs
		Eval('l' & $i)
	Next
EndFunc
 
Верх