Pull to refresh

Comments 48

UFO just landed and posted this here
Иначе минификатор будет думать, что все ваши переменные глобальные и не будет их оптимизировать — не будет сокращать имя переменной.
Странно, что опции для минификатора нету, типа «воспринимать как локальный контекст» =(
Приемы ручного сжатия напомнили, как мы участвовали в Time Limit Exceeded — индийский контест на решение задач на C так, чтобы программа получалась минимальной длины. Славно мы тогда поизвратились, я о C столько нового узнала :-)
индийский контест

чтобы программа получалась минимальной длины

Налицо парадокс :)
Ннэ, так учатся писать нечитабельный код. Проведут соревнование, а потом разбирают решения-победители и берут на вооружение самые чудовищные приемы :-)
Вообще можно ещё код сжать в png. Загрузчик кода из png, разумеется, тоже нужен будет, но размер таким образом можно уменьшить, например, и со 123 кб до 30 кб (как показывает практика). :)
загрузчик под килобайт вроде весит
Здорово — распаковщик в 109 байт + 90 байт накладных расходов. Правда этот подход в таком виде в каком есть не годится для js1k (запрещены внешние ресурсы). Если создавать картинку с image:data, то получим +30-40% к весу картинки. И не понятно будет ли оправдано это.

Вобщем прикинул: у вас картинка весит 753 байта, а кода в ней на 1059 (хотя я думал там будет 1059*4 байт ибо RGBA, почему вы брали каждый 4-й элемент, храните ещё что-то в RGB?). С data:image мы получим около 1054 байт + 100 байт распаковщик (можно оптимизировать если точить под js1k). Если занимать все пространство RGBA, то минимизированный скрипт можно ужать ещё в 5-6 раз!

Имея картинку в 650 байт (910 image:data) в неё можно засунуть около 3640 байт ужатого скрипта. Плюс 100 байт оптимизированный под js1k распаковщик. В сумме получим 1010 байт чистого кода, который теоретически должен развернуться до 3640 байт.

Поправьте если что не так.
Есть вариант без внешних ресурсов :) bolknote.ru/files/tank-1k-game-2/ (правда, я знаю как его ещё уменьшить).
Вобщем прикинул: у вас картинка весит 753 байта, а кода в ней на 1059 (хотя я думал там будет 1059*4 байт ибо RGBA, почему вы брали каждый 4-й элемент, храните ещё что-то в RGB?)
Я вообще хотел класть во все четыре компоненты, но сжимается лучше всего выбранный вариант.

Да, верно. Тут это и правда неуместно будет, т.к. цифры другие. Здесь это было реализовано и в рамках 10 кб это будет уместно. Не подумал.
10кб тоже интересный формат, но мало кому доступен — слишком много времени уходит на написание и оптимизацию.
Восхитительно! Благодарю за наводку.
var a='lineTo';c[a](150,150);c[a](150,200);c[a](150,250);c[a](250,350);c[a](450,350);
c[a='lineTo'](150,150);c[a](150,200);c[a](150,250);c[a](250,350);c[a](450,350);

Вообще как-то негусто приёмов описано.
c[a='lineTo'](150,150);c[a](150,200);c[a](150,250);c[a](250,350);c[a](450,350);

l=c.lineTo;l(150,150);l(150,200);l(150,250);l(250,350);l(450,350);
Серёг, или я торможу или lineTo получит в this window.
не, это я торможу :) Забыл про контекст
23+11*N vs 15+14*N
С семи вызовов это становится выгодней, а если выкинуть «var » в начале, то — с пяти.
Ну да, все зависит от приложения)
попробуйте для сжатия compressorrater.thruhere.net/ для меня там лучшим оказался Packer (Version 3.1) + допиливаю руками названия функций которые он не умеет сжимать. в моем случае Packer оказался на 10% лучше UglifyJS. Пишу тетрис. Пытаюсь затолкать 2048 байт. осталось еще 100 байт срезать, уж не знаю где еще :)
или я чегото не понял, или обясните мне: почему не использовали gcc? он очень качественно все делает и Вам бы не пришлось почти ничего оптимизировать руками. Почему о нем нету ни слова?
ага, code.google.com/closure/
Куча опций оптимизаций, сам сжимаю только им — по анализам, вроде самый оптимальный
GCC Advanced=on сжал мой скрипт до 1100 байт, UglifyJS — 1048, Packer 3.1 — 1049. Притом Packer и GCC коверкают порядок переменных (d,g,f вместо a,b,c) и от обрамляющего замыкания невозможно сразу избавиться. Если вы в GCC пользуетесь особыми настройками, то посвятите.
хм… странно, я пробовал пакером и gcc свои скрипты — gcc выиграл во много раз. конкретно по цифрам могу написать вечером

для gcc advanced нужно приводить код в спрециальный вид, собственно как и для uglyjs только свои правила.
Однако… Это не тот gcc, о котором все подумали :)
ну конечно не тот. я думал раз тема про JS все поймут о чем я ;)
Вроде бы не нашел у вас совет такого рода:
Если часто используется какой либо метод, например Math, можно сократить код так:
var m = Math;
И вызывать, например, так: m.abs();

Возможно я туплю и glifyJS это все уже сам делает.
на сколько я понимаю любой пакер делаем именно так, вычленяет одинаковые строки и заносит их в глобальные переменные до которых потом доступается.
9. Замените циклы for на while, избавьтесь от оптимизаций счетчиков c = smth.length
Потом замените while на for и получите ещё N байт ;)
i=smth.length;while(i--)do(i);
for(i=smth.length;i--;)do(i);


13. Удалите двойные и одинарные кавычки из атрибутов вашего HTML кода <div id=«aaa»> — <div a=aaa>
14. Замените строки в id элементов на числа <div id=aaa> — <div a=1>

Почему бы не создавать собственные элементы? Например, <r>. Вроде бы и html короче и путь в querySelectorAll. Конечно, с канвасом так не выйдет.
Дельно, правда опера не умеет вызывать события в атрибутах (onclick) у своих элементов <r>
<z onclick=alert(1)>qqq</z>
Действительно. Прям как у ie. Чтож, есть элементы a,b,i,p,q,s,u + значительное количество двубуквенных.
Кстати, иногда имеет смысл сделать подобную оптимизацию:
__fillStyle__ = 'fillStyle',
__fillRect__  = 'fillRect',
// =>
__fill__ = 'fill',
__fillStyle__ = __fill__ + 'Style',
__fillRect__  = __fill__ + 'Rect'


Особенно в паре с другими оптимизациями:
__fillStyle__ = 'fillStyle',
__fillRect__  = 'fillRect',
// =>
__fill__   = 'fill',
__stroke__ = 'stroke',
__Style__  = 'Style',
__Rect__   = 'Rect',
__fillStyle__   = __fill__   + __Style__,
__fillRect__    = __fill__   + __Rect__,
__strokeStyle__ = __stroke__ + __Style__,
__strokeRect__  = __stroke__ + __Rect__,


И, особо, при использовании длинных повторяющихся названий:
__getElement__             =  'getElement',
__getElementById__         = __getElement__ + 'ById',
__getElementsByTagName__   = __getElement__ + 'sByTagName',
__getElementsByClassName__ = __getElement__ + 'sByClassName',
В 1кб это не выгодно, пытался так сделать, сужу по своему опыту
ctx.f = ctx.fillRect;
ctx.__defineSetter__(«s», function (arg) { this.fillStyle = arg })

ctx.s = 'green';
ctx.f(5, 5, 25, 25);
Ещё читал вариант, если необходимо использоваться сообственные функции, то лучше создать одну функцию, а внутри сделать ветвление зависимо от первого параметра.
function foo () {
  // foo code
}
function bar () {
  // bar code
}
function qux () {
  // qux code
}

// =>

function g (fn) {
  if (fn == 'foo') {
    // foo code
  }
  if (fn == 'bar') {
    // bar code
  }
  if (fn == 'qux') {
    // qux code
  }
}

В таком виде не очень подходит для событий — основное место скоплений функций, но можно отфильтровать по event.type.
function g(e,t) {
  t = e.type;
  t=='click'&&code;
  t=='keyup'&&code;
  t=='keydown'&&code;
}
Sign up to leave a comment.

Articles