Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Оптимизация: int vs uint, i+=1 vs i++ и т.д. (http://www.flasher.ru/forum/showthread.php?t=109099)

WindWalker 07.03.2008 03:56

Оптимизация: int vs uint, i+=1 vs i++ и т.д.
 
Провёл небольшое исследование.
1. Что лучше: int или uint, и почему вообще между ними есть разница.
2. Что лучше: i+=1 или i++.

Исследование проводилось следующим образом.
Нижеописанный класс был откомпилирован с помощью командного компилятора из Flex SDK (надо отметить, что компилятор Flash CS3 выдаёт те же результаты).
Затем полученный .swf был декомпилирован с помощью abcdump из проекта Tamarin.

Код:

package {
        public class Test {
                private var a:int;
                private var b:uint;

                private  function int_field():void {
                        a=0;
                        a++;
                        a+=1;
                }

                private  function uint_field():void {
                        b=0;
                        b++;
                        b+=1;
                }

                private  function int_local():void {
                        var c:int;
                        c=0;
                        c++;
                        c+=1;
                }

                private  function uint_local():void {
                        var d:uint;
                        d=0;
                        d++;
                        d+=1;
                }
        }

}

Итого, у нас есть 3 операции, и 4 случая их использования: для локальной переменной и для поля, для uint и для int.

Вот так выглядит присвоение x = 0:
Поле int:
Код:

findproperty          private::a
pushbyte              0
initproperty          private::a

Поле uint:
Код:

findproperty          private::b
pushbyte              0
initproperty          private::b

Локальная int:
Код:

pushbyte              0
setlocal1

Локальная uint:
Код:

pushbyte              0
convert_u           
setlocal1

Вот так выглядит i++:

Поле int:
Код:

findpropstrict        private::a
dup                 
setlocal1           
getproperty          private::a
increment_i         
setlocal2           
getlocal1           
getlocal2           
setproperty          private::a
kill                  2
kill                  1

Поле uint:
Код:

findpropstrict        private::b
dup                 
setlocal1           
getproperty          private::b
increment           
setlocal2           
getlocal1           
getlocal2           
setproperty          private::b
kill                  2
kill                  1

Локальная int:
Код:

inclocal_i            1
Локальная uint:
Код:

getlocal1           
increment           
convert_u           
setlocal1

Вот так выглядит i+=1:

Поле int:
Код:

findproperty          private::a
getlex                private::a
pushbyte              1
add                 
initproperty          private::a

Поле uint:
Код:

findproperty          private::b
getlex                private::b
pushbyte              1
add                 
initproperty          private::b

Локальная int:
Код:

getlocal1           
pushbyte              1
add                 
convert_i           
setlocal1

Локальная uint:
Код:

getlocal1           
pushbyte              1
add                 
convert_u           
setlocal1


Выводы:

1. Для полей нет разницы между int и uint (кроме области допустимых значений, разумеется).
2. При работе с локальными переменными типа uint часто используется инструкция конвертации convert_u, которая хоть и не значительно, но тем не менее может снизить произодительность. convert_i тоже иногда используется, но реже.
3. При работе с полями объекта выражение i+=1 компилируется в гораздо меньшее количество инструкций, чем i++ и выполняется значительно быстрее.
4. Наиболее быстрым выражением является i++ если i - это локальная переменная типа int. В этом случае выражение компилируется всего в одну инструкцию AVM2. Если i типа uint, то получается уже 4 инструкции.

Gaen 07.03.2008 09:04

Занятненько...
Спасибо.

terbooter 07.03.2008 12:46

Спасибо.
А я давно подозревал и везде использовал int вместо uint.
uint только в константах.

etc 07.03.2008 13:13

Не забывайте, что это разница в скорости актуальна при использовании полей класса, а не локальных переменных.

Iv 07.03.2008 13:13

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

Torero 07.03.2008 13:14

Спасибо. Интересно. На буржуйском сайте тайминг проводили - самый быстрый цикл выглядел следующим образом:
Код:

var i:int;
while(i++<100000){
        ...
}


WindWalker 07.03.2008 14:10

Конечно, всё ещё во многом зависит от того, как байт-код будет переведён в нативнй код jit-компилятором.
Однако, здравый смысл подсказывает, что
Код:

inclocal_i            1
должно работать быстрее, чем
Код:

getlocal1           
increment           
convert_u           
setlocal1

Хотя не исключён вариант, что inclocal_i компилируется в итоге абсолютно в то же самое, что и 4 инструкции.
А колупать исходники AVM2 как-то не очень хочется :)

2morrowMan 07.03.2008 18:31

Использовался Flex Builder 3 ?

Iv 07.03.2008 19:28

Из классики:

На первом этапе программирования нужно сосредоточиться на правильной архитектуре приложения, читабельности кода, прозрачности и правильности логики.
Только после окончания создания приложения следует протестировать производительность приложения, и только затем, на основании конкретных результатов тестов производить пошаговую оптимизацию, каждый раз обращая внимание на самые проблемные места кода.

К чему это я свои 5 копеек в этот флейм тащу:
Производительность конкретного кода цикла здесь обсуждается не в рамках единого процесса оптимизации, а как отдельная фишка.

Боюсь, что знание методологии оптимизации кода в данном топике подменяется на следование ничему не значащим фактам.
Почему не значащим? Потому, что один лишний вызов метода съест с лихвой всю экономию на всех циклах за всё время работы приложения.

Не питайте иллюзий, что сабж вам поможет писать быстрые приложения.

ИМХО

WindWalker 07.03.2008 23:48

Цитата:

Сообщение от 2morrowMan
Использовался Flex Builder 3 ?

Нет, Flex Builder вообще никакой не использовался :)
Использовался консольный компилятор из Flex 2 SDK.
Кстати, хорошая идея! Надо проверить, в Flex 3 SDK, может быть что-то изменилось.


Цитата:

Сообщение от Iv
Из классики:
Только после окончания создания приложения следует протестировать производительность приложения, и только затем, на основании конкретных результатов тестов производить пошаговую оптимизацию, каждый раз обращая внимание на самые проблемные места кода.
.....
Почему не значащим? Потому, что один лишний вызов метода съест с лихвой всю экономию на всех циклах за всё время работы приложения.

А с этим никто и не спорит.

Тем не менее, для того, чтобы оптимизировать, необходимо знать как влияют на быстродействие те или иные операции.
Например, то, что вызов методов в AS3 происходит крайне медленно - это ведь тоже не с потолка взято, а опять же было проверено экспериментально.

И, скажем, тот факт, что в AS1/AS2 использование x & 1 вместо x % 2 не давало никакого выигрыша, тоже кто-то когда-то проверил.

Это я к тому, что методология методологией, но без знания быстродействия конкретных элементарных операций будет вообще непонятно КАК оптимизировать (за исключением оптимизации алгоритма, разумеется).


Часовой пояс GMT +4, время: 08:47.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.