Оптимизируя оптимизированного

Воскресным утром я осуществил то, что давно собирался сделать: всерьез взялся за Action Script 3. Разобравшись в синтаксисе и принципах я решил сделать что-то простое и ненавязчивое, но в то же время дающее подергать за самые частые задачи, которые приходится делать, создавая флеш-сайты или флеш-приложения. Ничего сложного в AS3, кроме огромного количества файлов для любого хоть чуточку серьезного проекта, нет. Мало того, всплыли воспоминания о юности, в которой я стал магистром технических наук и software engineer — дорвавшись до нормального объектно-ориентированного программирования я забыл о еде, питье и вообще почти обо всем.
Теперь о поставленной себе задаче. Вчера за quattro formaggi Юра рассказал об интересном посте, который он сейчас пишет. Я предложил проиллюстрировать, что одну из описываемых задач оптимальнее всего делать на флеше. Этой задачей я и занялся, сделав флеш-ролик используя AS3. Если бы я писал на AS2, то все заняло бы не более 20 минут. С копанием в устройстве и работе Action Script 3 я справился за 40 минут. Итак, что же я делал.
На экране есть несколько блоков, они могут располагаться друг за другом таким образом, чтобы всегда оптимально заполнять окно. У них есть максимальная ширина, но они могут изменять ее в меньшую сторону и прыгать со строки на строку. Картинка ниже сделает это объяснение более понятным:

Приводить весь первоначальный код не буду, он слишком велик для публикации просто так в посте. Кто хочет, может скачать и полюбоваться. Первоначальный же .fla не сохранился, но он не так уж необходим ;)
После компиляции флеша я получил аккуратный файл размером 4 Кбайта, отправил Юре и отправился читать Dark Blue Воррена Эллиса (Warren Ellis). После прочтения комикса мне захотелось решить какую-нибудь головоломку и я взялся за оптимизацию флеш-ролика. Достигнуть желаемых 1024 байтов мне не удалось, но результат получился удовлетворительный.
Оптимизация символов
Первым делом я, разумеется, убрал встраивание шрифта, которым показывались цифры. Для этого достаточно и _sans. Само текстовое поле сделал шириной в два символа и удалил единицу, которую написал в нем еще при создании. Половину размера как рукой сняло ;)
После этого, я избавился от всех групп: вместо размещения блика в группе над нижней плашкой, я поднял его в слой повыше, сэкономив несколько байтов. Везде, где это было возможно, я убрал прозрачность: Alpha: 100% и никаких возражений!
Оптимизация имен
Следующим шагом стала оптимизация имен. Текстовое поле из txt стало просто t, buttonBackground — b и так далее. Это также сэкономило несколько десятков байтов. Функция arr(e:Event) в файле main.as стала называться просто a(e:Event). Поскольку она вызывается при изменении размеров окна listener’ом, это помогло уменьшить размер результирующего swf. Изменения же имен переменных никакого влияния на размер файла не оказали бы.
Оптимизация исходного кода
Когда оказалось, что во флеше уже менять нечего, я вспомнил как приятно было сдавать экзамен по системному программированию на третьем курсе. Мы проболтали с преподавателем часа три о методах оптимизации программ при компиляции.
Все переменные типа Number я сделал int, после чего убрал ненужные округления. Например, если при подсчете переменной типа Number мне необходимо было указывать
var colw:Number=Math.floor(stage.stageWidth/cols);
то после того, как она стала int, операция / взяла на себя функции целочисленного деления:
var colw:int=stage.stageWidth/cols;
После этого, не задумываясь ни секунды, я вынес повторяющийся кусок с расстановкой блоков в отдельную функцию. Поскольку эта функция вызывается при изменении размеров окна, я записал ее прямо в функцию, вызываемую listener’ом, которую, как мы уже знаем, стали звать a:
stage.addEventListener(Event.RESIZE, a);…function a(e:Event):void {var cols:int=Math.ceil(stage.stageWidth/300);var colw:int=stage.stageWidth/cols;for (var i:int = 0; i < 30; i++) {var nB:Object=getChildAt(i);nB.b.width=colw;nB.x=i%cols*colw;nB.y=Math.floor(i/cols)*43;}}
Для вызова этой функции в конструкторе пришлось добавить следующее:
var e:Event;a(e);
Эта конструкция добавила 2 байта к размеру swf, но до этого мы сэкономили гораздо больше.
В конце-концов я убрал проверки деления на ноль (флеш даже не поморщился) и скомпилировал проект снова. Юра предостерег меня, чтобы я не увлекся и не сделал оптимизацию настолько хорошей, что swf станет отрицательного размера. Мир в безопасности: БАК запущен, а файл с отрицательным размером у меня не получился. После всех манипуляций swf стал занимать 1149 байт. Больше в нем оптимизировать нечего. Для сравнения можно скачать получившийся проект (zip, 12,7 Кбайта). Мне кажется, что оптимизировать там уже нечего ;)


