Flash-платформа

индекс
119,86

Оптимизация Flash. Работа с элементарными типами и функциями

Технология Adobe Flash на данный момент лидирует в области мультимедиа в сети Интернет, на ее основе построено огромное количество RIA(Rich Internet Application), сайтов, игр; с помощью нее создается подавляющее число баннеров и презентаций. С выходом Action script 3, а, особенно, Adobe Flash Player 10.x возможности этой технологии возросли многократно, что позволило создавать более мощные и функциональные приложения для сети Интернет. Снежным комом растет количество online-игр и сервисов, решающих огромный круг задач (от заливки файлов на файловые хостинги, до графических редакторов, которые немногим уступают Adobe Photoshop по функциональности).

С развитием этой технологии появилось множество специалистов, занимающихся разработкой приложений на Flash. А рост интереса рынка к этой технологии требует от специалистов большего профессионализма, одним из факторов которого является более глубокое понимание Flash'а и опыт по более продуктивному использованию этой технологии.

Я занимаюсь флешем уже несколько лет и могу сказать с определенной долей уверенности, что существует некоторое количество нюансов, которые помогают более эффективно использовать ресурсы компьютера и Flash. Я не ставил себе задачу писать руководство по оптимизации, я лишь хотел показать, как ведут себя некоторые типы данных при большом количестве вычислений, что особенно актуально при разработке Flash-игр. Я поставил себе цель провести исследование по этой теме и предоставить его результаты Вам.
Принятие решения по поводу того, как использовать полученную информацию, ложится на твои плечи %habrauser%.

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

Для начала полный список тестов. Сравниваю скорость работы:

  1. Number, uint, int и не типизированная переменная(далее *).
  2. String и *.
  3. Array и Vector содержащие простой тип (Number).
  4. Array и Vector содержащие сложный тип.
  5. Типов доступа к Object: Object.variable и Object[“variable”]
  6. Типов доступа к переменной класса: прямой (public переменная), функция и setter/getter.

С каждым тестом я буду приводить по два графика отображающих результаты исследуемых операций. Ось Y отображает время в миллисекундах, затраченное на 10^6 операций. Если у вас возникнут сомнения или вам захочется провести тест самостоятельно, то в конце статьи Вам будет доступна ссылка на скачивание архива с проектами на Flex/FlashDevelop. Все тесты были проведены на 10ой версии Flash Player.

И так начнем.

Сравнение по скорости работы типы данных Number, uint, int и *, относительно операций «++», «+=» и «а=а+1». В данном тесте, исследовалась простейшая, казалось бы, операция инкрементации в контексте разных типов данных. (Test_1, далее в скобочках я буду помечать таким образом названия проектов созданных для проведения каждого конкретного теста).

image

image

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

Сравнение скорости работы String и * в записи, чтении и добавлении(операцией += добавлялся один символ). (Test_2)

image

image

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

Сравнений скорости работы Array и Vector содержащих простой тип данных (Number)
(Test_3_FD)

image

image

Как видно на чтении особой разницы не заметно, но при записи становится очевидно, что Vector оказывается быстрее, значит при оптимизации какой либо программы это может помочь, правда есть одно ограничение: Vector это фича 10го плеера, а значит если проект коммерческий и одно из требований 9ая версия, то про такой вариант оптимизации можно забыть.

Сравнений скорости работы Array и Vector содержащих сложный тип данных (экземпляр класса).
(Test_4_FD)

Код класса использующегося в эксперименте.

package
{
/**
* ...
* @author Shirobok Pavel aka ramshteks
*/
public class TestClass
{
private var _testvar:Number;
public var _testpublicvar:Number;
public function TestClass() {}

public function testFunc():void {
trace("test");
}

public function get testvar():Number { return _testvar; }

public function set testvar(value:Number):void
{
_testvar = value;
}
}
}


image

image

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

Сравнение скорости доступа к свойству экземпляра класса Object, методом прямого обращение (Object.variable) и строковым способом (Object[“variable”]).
(Test_6_FD)

image

image

Прямое обращение явно быстрее, но не намного.

Сравнение скорости работы типов доступа к переменной класса: прямой(public переменная), функция и setter/getter. (Test_5_FD)

Класс над которым проводился эксперимент.
package
{
/**
* ...
* @author Shirobok Pavel aka ramshteks
*/
public class TestClass
{
public var testvar:uint;
public function TestClass() {}

public function setVar(value:uint):void {
testvar = value;
}

public function getVar():uint {
return testvar;
}

public function get testsetget():uint { return testvar; }

public function set testsetget(value:uint):void
{
testvar = value;
}
}
}


image

image

При любом виде доступа простая public переменная показывает отличное время, и понятно почему — не затрачивается время на работу с функциями. На записи обычная функция и сеттер практически идут наравне, а вот чтение делает быстрее геттер. В итоге у нас есть прекрасный способ оптимизировать программу в ущерб качества кода. Вы можете закидать меня помидорками Черри за это, но лично меня он спасал не раз.

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

Удачи!

Исходники тестов slil.ru/28768108
+30
10 марта 2010, 20:16
33

комментарии (41)

0
flashguy #
Интересные показатели у последнего теста (Test_5_FD). Однако если требуется инвалидация свойств компонентов то сеттер почти незаменим.
0
ramshteks #
да не спорю, есть места где сеттер незаменим, но в определенных местах такой роскошью можно пожертвовать ради ускорения кода.

А чем интересные? они кажутся вам сомнительными?
0
flashguy #
Почему же сомнительные. Интересные в плане никогда сам не проводил таких тестов :) и даже не мог предположить что доступ к данным через геттер/сеттер и функции могут отличатся по скорости.
–1
ramshteks #
я сталкивался с подобными вещами когда писал разные ресурсоемкие лабы по учебе. Возникла проблема, прога медленно работает. Оптимизировал код везде где только мог, в итоге выяснилось что время одного цикла было просто огромно, а все из-за того что использовалась функция, которую я писал… пришлось от нее избавиться, и весь код из нее перенести в тело цикла, в итоге скорость исполнения скрипта выросла примерно в два раза. После этого я понял, что во флеше в отношении именно оптимизации много подводных камней.
0
kresteleff #
то что скорость работы через функцию медленнее чем код написанный внутри цикла это нормально. Причем не только во флеше. но делать выводы из этого что геттер/сеттер и функции могут отличатся по скорости не логично
0
nukie #
Вообще это чуть-ли не нормальная ) практика для игр, особенно тех, код которых работает в виртуальной машине. Даже в некоторых игровых фреймворках, используют такой подход.
+2
sse #
Такой вопрос: у вас что, программы из одних геттеров/сеттеров состоят, что ли? Вы не пробовали вместо насквозь синтетических тестов (на которых выигрыш, кстати, в половине случаев находится в пределах погрености) попробовать привести примеры реальных приложений, которые бы ощутимо выиграли от замены одного на другое?

Ну, собственно, что интересует:
— удельно количество операций get/set по отношению к объему всего байткода;
— удельное время, застраченное на get/set, по отношению ко всему затраченному в программе времени.

После этого, как мне кажется, имеет смысл говорить об возможностях ускорения
+1
ramshteks #
Такс… интересно. Эту тему по оптимизации я хотел продолжать, спасибо за подкинутую идею для следующих тестов. Обязательно проверю и приведу интересующие вас данные =)
0
nukie #
Я бы добавил, что не столько реальных приложений, сколько приложений реального времени, с большим количеством динамических, однотипных объектов.
0
WhiteD #
"… казалось бы, операция итерирования..."
Не казалось бы. Эта операция называется инкрементом.
+1
ramshteks #
тьфу ты. Надо же было так облажаться
–3
mrskam #
А если не трудно, повторите тесты на 10.1 (который бета3 сейчас).
Думаю, будет интересно взглянуть на результаты.
–2
ramshteks #
надо будет попробовать.
+2
kresteleff #
Сравнивать скорость обработки типизированых переменных с нетипизированными это абсурд. И так понятно что на приведение к нужному типу уйдет какое-то время.
Сомнительны результаты в тесте сравнение скорости доступа к свойствам экземплярам класса.
А что касается последнего теста, то использование публичных методов или сеттеров\геттеров это только дело вкуса, но не скорости и оптимизации. Да и сравнение переменной и методов это тоже не правильно. И так понятно, что обращение к переменной будет быстрее.

Вы говорите, что это приведет к значительному увеличению производительности — это заблуждение! По большому счету, ни к чему это не приведет

ЗЫ А вот еще тесты производительности в графиках. И не надо ничего скачивать и компилировать
businessintelligence.me/projects/performance_tester/performanceTester.html
0
ramshteks #
возможно я не совсем верно выразился в самом посте. Возможно не логично и не корректно. Я лишь хотел показать разницу. Во всех тестах я преследовал именно эту цель. Насчет типизации… ну что я могу сказать, да очевидно, но мой опыт общения на форумах показывает, что это очевидно далеко не всем. А тест с сеттером и переменной, тут задача была в том, чтобы показать, что иногда ради ускорения кода, проверки на валидность передаваемых данных иногда выгоднее провести не в коде сеттера, а во вне.
+1
kresteleff #
Не читайте советских газет до обеда, и форумов тоже.
За отсутствие типизации надо руки отрывать по самую шею. Типизация не только оптимизирует код, но делает его более читабельным.

Выносить код проверки из метода во вне — это логическая ошибка проектирования. Этого делать нельзя. Что же касается ускорение кода, то оно будет не существенно и даже не заметно.

Кстати, ты подписан на гугл группу ruFlash?
–5
ramshteks #
я был уверен, что люди будут придираться к этому)
Я понимаю, что такой подход (вынесение валидации) это ошибка. Ошибка по многим причинам. Для меня это очевидно. Но качеством кода, я порой готов пожертвовать, если это единственный путь ускорить работу проги. Естественно я сделаю такой финт только после того, как не найду не одного другого способа ускорить код.

Нет не подписан, что это, где взять и что я там хорошего могу почерпнуть?)
–1
kresteleff #
groups.google.com/group/ruflash/browse_thread/thread/24d2373622fab21c/c1278837962684bb
почитай, там ближе к концу дискуссии Иван Дембицкий прекрасно высказывается на эту тему

Что такое ruFlash это сюда groups.google.com/group/ruFlash
что почерпнуть, сам решай)
0
ramshteks #
вообщем меня к сожалению не поняли. приведу пример.
Писал лабораторную работу. Называлась она так Робастная оценка регрессии. Конечно это только лабораторная работа, но это как раз тот случай когда мне удалось значительно снизить время просчета за счет «микрооптимизаций». Не спрашивайте почему я довольно ресурсоемкий процесс реализовывал на флеше, а не на с++ (хотя мог), но суть в том, что… вообщем я все объяснил в предыдущем посте.

Все таки надо было оч подробно описать в начале статьи, что именно я хочу показать =)
Архитектура, проектирование и все эти замечательные слова… я с ними знаком. Занимаюсь флешем уже давно я считаю. С 2005 где то года, зарабатывать начал в 2007. И книжек прочитал много и статей. Я просто пытаюсь смотреть на все с несколько иной стороны, а меня тыкают личиком в статьи где говорится то что я и так знаю. Извините может я вас не так понял конечно =)
–2
ramshteks #
перечитал себя… вы уж не сочтите меня зазнавшимся… просто чувствую что меня не понимают.
+5
kresteleff #
Личиком вас никто никуда не тыкал) Опираясь на вашу статью и комментарии, я предположил, что у вас отсутствуют некоторые базовые знания. И неправильный, как по мне, взгляд на проблему усовершенствование кода. Лучшее враг хорошему!

То, что Вы пытаетесь смотать на все с иной стороны — это хорошо. Но вы написали статью, не в свой блог. Сюда может прийти человек, с маленьким опытом работы во флеше, который только начинает изучать его. Он прочитает это, и решит, что подобным вещам надо уделять особое внимание. И будет усердно оптимизировать свой код, тратя свое время по сути попусту. Потому что, во-первых, подобная оптимизация, ни как не отразится на скорости проекта, а наоборот может только привести к возникновению ошибок. Во-вторых, у человека может развиться плохой стиль написания кода. Первое исправить можно, а второе уже будет сложнее, а в некоторых случаях невозможно :)

Я могу особо акцентировать внимание на моменты в которых я не согласен
1. Сравнение с не типизированной переменной. Код надо обязательно типизировать.
2. функция и setter/getter по сути одно и тоже. Выбор что использовать — это всего лишь стиль программирование
3. Сравнение публичного атрибута и публичного метода — это абсурд. Вообще публичные атрибуты следует использовать в узком кругу мест. Публичные атрибуты — это плохой и очень опасный стиль кода, очень часто приводящий к ошибкам.
4. >> иногда ради ускорения кода, проверки на валидность передаваемых данных иногда выгоднее провести не в коде сеттера, а во вне.
Это очень плохой пример, сто процентов приведет к ошибке, потому что в этой случае придется таскать за собой проверку везде и всюду.
5. Значительное увеличение производительности. Если при подобной оптимизации у Вас происходит значительное увеличение производительности — это значит что ваш код спроектирован и написан плохо.

0
ramshteks #
возможно я действительно смотрю на это со стороны вредной для читателя.
+1
Bright #
Приведите, пожалуйста, примеры где данные оптимизации вам помогали. Сейчас это просто набор синтетических тестов, на основе которых вы строите выводы. Притом некоторые из выводов похожи на «вредные» советы =)
0
ramshteks #
я уже приводил пример habrahabr.ru/blogs/Flash_Platform/87026/#comment_2605742
0
fzn7 #
А зря не на c++ компильнул бы в алхимией и получил-бы свои 15% прироста производительности.
+2
lsdima #
Тесты с Array и Vector, в вашем случае быссмысленны, пока вы не указываете, какими методами проводили чтение/запись.
0
mono2k #
1) попробуйте для доступа к вектору использовать int вместо uint, чтение из Vector оптимизировано при обращении по интовому индексу.

2) сравнивая int, uint и Number следует помнить, что по крайней мере int (за uint не ручаюсь) внутренне устроен очень хитро, как и вся система типизации в рантайме флешплеера.
Первые несколько бит хэндла, описывающего переменну, хранят некий флаг (тип), который сообщает о природе содержимого оставшихся битов. Если флаг выставлен в XXX, то оставшиеся биты содержат числовое значение данной переменной, в противном случае это своего рода индекс-ссылка-указатель на то место в памяти, где флешплеер хранит объект, соответствующий переменной.
Отсюда вытекает интересное свойство — если проводить операции над int'ами с малыми значениями (вроде бы до 2^24), то это будет происходить очень быстро, если операнды будут находится во всем доступном диапазоне, то скорость выполнения операций будет примерно равна скорости работы с Number, так как (если не ошибаюсь) отдельного класса для int'ов не существует и в этом случае int = Number для внутренностей плеера.
(это так же на индексацию вектора влияет)

а вообще тесты конечно ни о чем, увы, хотя начинание похвальное :-)

0
BlooDHounD #
а можно узнать в каком окружении проводились тесты? были ли сборки дебаговыми или релизными? тесты проводились прямо во флексе, или же при его помощи были просто построены графики?
–1
ramshteks #
какие люди)
Вообщем то тут вы меня озадачили, так как я начал сомневаться немного…
первые два теста проводились в самом флексе, а остальные я проводил во FlashDevelop. Плеер везде дебажный…
0
BlooDHounD #
плэйер не важен. важно, что вы компилили флэшку с дебаг инфой.
собственно советую повторить тесты во FlashIDE через CTRL+ENTER. где флэшка собирается без мусора извращающего тесты.
–1
ramshteks #
окей
0
nepx #
Кстати, почему FlashIDE компилит чище чем FlexSDK-компилятор? У меня при компиляции FlexSDK-компилятором, даже если уменьшаешь объем кода, размер выходного SWF-файла все равно увеличивается :(
P.S. Привет обществу flasher.ru на хабре!
–1
ramshteks #
возможно потому, что так или иначе флекс привязывает свой фреймворк. Но это предположение.
–1
nepx #
Я пишу под FDT3, под pure as3, т.е. у меня линкована только playerglobal.swc
–1
ramshteks #
тогда подсказать ничего не могу. FDT3 — это FlashDevelop?) или что...?)
–1
nepx #
FDT3 — Flash Development Tool — вроде считается самой каченной средой разработки.
www.fdt.powerflasher.com/developer-tools/fdt-3/home/
0
ramshteks #
хм… посмотрел. Интересная, но дорогая вещь. Возьму на заметку, может как нибудь попробую
0
nepx #
Странно, что Вы про нее не знали.
Кстати, 30 дней бесплатно.
0
BlooDHounD #
заблуждение. для АС3 ваще нет прокаченых тулзов. у всех свои минусы и плюсы. нету ни одной ИДЕ, которая объединяла бы все плюсы.
+1
BlooDHounD #
скомпилируйте через CTRL+SHIFT+ENTER получите тоже самое. просто по умолчанию во флэше компилится не дебаг-версия, а релизная. в отличии от флекса.
0
nepx #
Ха! Спасибо.
Откомпилил в FDT релизную, получил 71Кб против 104Кб!

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.