Клиентская оптимизация

индекс
163,90

Ускорение загрузки AJAX приложения, + предзагрузка изображений

Всё началось с создания сложного AJAX приложения с применением java технологий GWT, GXT, Spring, Hibernate, Terracota, AndroMDA, ActiveMQ и множеством других волшебных звуков за которыми прячется вся мощь и могущество java технологий создаваемых десятками тысяч гениальнейших программистов уже второе тысячелетие подряд …

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

Входные данные: размер текстовых данных js, css, xml, html, images коло ~1,2MБ(+ флэш), время загрузки в Москве более полутора минут, при хождении по ссылкам заметное время(1-15 секунд) на загрузку картинок, при повторном обращении картинка загружалась повторно.

Данные приблизительные по следующим соображениям
1)GWT для каждого браузера генерирует свой js размер которого около 700КБ
2)Сначала была сделана оптимизация а потом пришла идея, что это может быть полезно сообществу

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

Сжатие контента средствами web сервера
Сервером оказался Tomcat. Файл настроек был интуитивно понятен, сделан с соблюдением формата xml и всё в нём было хорошо, сжатие было включено, был включен эффективный nio коннектор — но этот чудесный по всем описаниям коннектор не желал использовать компрессию.
Смена коннектора на идущий по умолчанию HTTP/1.1, заставила компрессию чудесными образом заработать. В голове поселилась мысль, как так, в старом добром коннекторе есть компрессия а в дите высоких технологий — нет? — тут что-то не так.
В процессе изучения документации по томкату выяснилось что компрессия есть. Также в документации оказалось ещё несколько любопытных опций позволяющих сжимать файлы по различным признакам таким как размер и тип файла, также можно указать качество компрессии.
Компрессия тем не менее от полученного знания не заработала.
Дальнейшие размышления о глубине, широте и высокой интегрированности java платформы подсказали мне, что возможно приложение может самостоятельно конфигурировать сервер под свои нужды.
Было принято решение проверить это предположение задав вопрос разработчикам, — как выяснилось java программисты действительно отключили эту функцию у всего приложения для nio коннектора так как она мешала работе чата.
Дальше в этом направлении всё шло предсказуемо. Java девелоперы пока очень заняты и не поправили багу. Компрессия работает с HTTP/1.1 а в файле конфигурации красуется закоментированный nio коннектор и 700КБ js файл стал весть уже 190КБ и это воспринималось как гора с плеч.

Кусочек конфигурационного файла настраивающего коннектор.
   <Connector port="8080" protocol="HTTP/1.1"
        maxThreads="64000" 
        connectionTimeout="20000"
        redirectPort="8443"
        proxyPort="80"
        compression="on"
        compressionMinSize="4000"
        noCompressionUserAgents="gozilla, traviata"
        compressableMimeType="text/html,text/xml,text/javascript,text/css" />

  <!--Connector port="8080" compression="on"
        protocol="org.apache.coyote.http11.Http11NioProtocol"
        connectionTimeout="20000"
        backlog="500"
        maxThreads="4"
        redirectPort="8443"
        proxyPort="80"
        compressionMinSize="2048"
        noCompressionUserAgents="gozilla, traviata"
        compressableMimeType="text/html,text/xml,text/javascript,text/css,application/x-javascript"
        socketBuffer="64000"/-->

* This source code was highlighted with Source Code Highlighter.
Думаю сам кусочек конфига будет полезен очень малому количеству пользователей, но знание возможности и подход к решению вопроса должен быть полезен большинству.

Отключение лишних файлов
Вторым делом было решено посмотреть что за js грузятся в таком количестве
Их грузилось около 10 штук и порядка 7 из них не относилось GWT ни каким образом. Как водится любопытство взяло верх и все непонятные js были отключены. Каково же было удивление, когда после чистки кэша и перезагрузки страницы всё прекрасно работало (в firefox 3.1 под Linux). Об этом факте было сообщено разработчикам приложения, с вопросом а действительно ли всё это используется? Разработчики после недолгого размышления оставили только один их предложенных мною к удалению файлов, сообщив что этот один необходим для IE. Тем не менее выкидывание 6 лишних запросов и порядка 70КБ жатого js кода существенно сокращало время загрузки.

Объединение файлов
Также была изучена возможность сливания файлов js в один файл, данная возможность оказалась не удобной на данном этапе развития проекта так как новые билды идут иногда по 3 за день, а возможность сливания файлов была ограничена двумя файлами несущественного размера. Возможно это будет сделано поже по средством простого скриптика на bash поставленного в крон :) `cat file1 file2 > file3; mv file 3 file1; egrep -v -o «file2» file.html > tmp.file.html; mv tmp.file.html file.html`, ну или как то так с необходимыми проверками и резервными копиями.

Сжатие js средствами yuicompressor
developer.yahoo.com/yui/compressor/
С целью ещё более сильного уменьшения был изучен оптимизатор от Yahoo YUI он действительно сокращал, пусть и несущественно, размер несжатого js файла прошедшего через обфускацию средствами GWT, но после сжатия коннектором размер файла был несколько большего размера чем файл без сжатия этим средством. По этой причине дальнейшие раскопки в данном направлении были прекращены.
$ java -jar yuicompressor-2.4.2.jar -o modified_script_yui.js --charset utf-8 --type js modified_script.js
$ ls -lh modified_script*
-rw-r--r-- 1 user user 725K 2009-10-13 11:49 modified_script.js
-rw-r--r-- 1 user user 719K 2009-10-13 11:51 modified_script_yui.js
$ gzip modified_script*
$ ls -lh modified_script*
-rw-r--r-- 1 user user 199K 2009-10-13 11:49 modified_script.js.gz
-rw-r--r-- 1 user user 203K 2009-10-13 11:51 modified_script_yui.js.gz


* This source code was highlighted with Source Code Highlighter.


Сжатие CSS средствами yuicompressor
CSS файл только один, в нём много пробельных символов и написан он без оптимизаций, по этой причине он был прогнан через yuicompressor но результат в конечном итоге был только в 700 байт что в моих масштабах было не существенно, по этой причине было решено не использовать yuicompressor в текущей активно разрабатываемой версии вообще.

$ java -jar yuicompressor-2.4.2.jar file.css -o file.css.yuic --type css
$ ls -lh file*
-rw-r--r-- 1 User User 38K 2009-10-06 08:26 file.css
-rw-r--r-- 1 User User 5.7K 2009-10-08 01:18 file.css.gz
-rw-r--r-- 1 User User 30K 2009-10-08 01:18 file.css.yuic
-rw-r--r-- 1 User User 5.0K 2009-10-08 01:19 file.css.yuic.gz


* This source code was highlighted with Source Code Highlighter.


Оптимизация изображений
Их порядка 600 штук. Было решено прогнать эти картинки через автоматизированные сервисы и это дало выигрыш приблизительно в 15 — 18% те около 1,5 мегабайт из 10 возможных.
К сожалению исходников большинства этих картинок не сохранилось а может изначально и не было так как они сразу приобретались в форматах png и jpg.

Дальнейшие эксперименты показали что методом брутфорса можно было бы добиться ещё 1% уменьшения по png файлам которых большинство и вероятно это будет сделано перед отправлением проекта в плавание.

Оптимизация картинок проводилась не мной по этому больше информации пока не дам

Оптимизация проводилась со знанием и пониманием
www.artlebedev.ru/tools/technogrette/img/

Географическое распределение серверов
В этот момент время загрузки колебалось от 15 до 30 секунд в Москве и порядка 4-6 секунд в Калифорнии. Эта несправедливость объяснялась местом расположения датацентра amazon. В хранилице amazon s3 к этому времени уже хранились все изображения.
aws.amazon.com/s3/.

Устранить это досадное недоразумение за разумные деньки помогло другое решение амазона aws.amazon.com/cloudfront/

После установки cloudfront время загрузки в Москве приравнялось времени загрузки в Калифорнии из чего можно сделать допущение что в большинстве мест на планете время загрузки равнялось 4-6секундам если это позволяла «последняя миля».

Предварительная загрузка изображений.
Оставалась ещё одна существенная проблема, ощутимое время загрузки изображений в процессе использования AJAX приложения.

Решилось это через создание скрипта предварительной загруки изображений. В задачи скрипта входил минимум задач.
1)Закачать изображения из заранее определённого списка
2)Удалять изображения из списка после закачки, даже если она неудачна
3)Останавливать закачку
4)Продолжать закачку

В процессе написания данного скрипта открылись некоторые интересные особенности js.
Закачка происходит асинхронно, поэтому обычный цикл(while, for) не подходил, так как 600 одновременно закачиваемых файлов подвешивали браузер на некоторое время в зависимости от мощности компьютера.

Это обходилось через вставку анонимной функции в onload и onerror которая вызывала родительскую функцию, те получалась рекурсия не позволяющая высвободить уже неиспользуемую память. Это проявилось в IE через ошибку «out of memory».

Эту рекурсию нужно было разорвать придумав эффективный вариант хвостовой рекурсии, позволяющий высвободить неиспользуемую память. Решение этой проблемы было найдено через использование таймера со значением 1.

preloadimg.js (внесены изменения Wed Oct 14 07:53:31 PDT 2009)
  1. stopPreloadImg = false;
  2. arrayImgCached = new Array();
  3. arrayImg = null;
  4. baseUrl = null;
  5.  
  6. function preloadImg(preloadArray, baseUrl) {
  7.   this.arrayImg = preloadArray;
  8.   this.baseUrl = baseUrl;
  9.  
  10.   cacheImage();
  11. }
  12.  
  13. function safeMemoryInRecursion() {window.setTimeout(cacheImage, 0)}
  14.  
  15. function cacheImage()
  16. {
  17.   if (arrayImg.length > 0 && stopPreloadImg == false) {
  18.     var img = new Image();
  19.     img.onerror = function(){safeMemoryInRecursion()};
  20.     img.onload = function(){safeMemoryInRecursion()};
  21.   img.src = baseUrl + arrayImg[0];
  22.     
  23.     arrayImg.shift();
  24.     arrayImgCached[window.arrayImgCached.length] = img;
  25.   }
  26. }
* This source code was highlighted with Source Code Highlighter.


Функцию предзагрузки изображений предполагалось использовать следующим образом

После введения этого кода в эксплуатацию, загрузка изображений перестала ощущаться вообще. Единственный случай когда видно загрузку картинок, если очень быстро ввести логин/пароль и идти на самую тяжёлую страницу, ожидается что в реальной жизни такое будет практически невероятным.
Итого
Сегодняшняя проверка приложения показала
Загружаемый размер вместе с флэшем 591КБ, из них
флэша 348КБ — эта часть оптимизировалась, но подробности мне известны недостаточно полно чтобы об этом что-то писать.
Html+js+xml+css = 243КБ
Время загрузки 5 — 10 секунд (есть отличие от заявленных выше 4-6 секунд, видимо произошли изменения на канале).
При переходе по внутренним страницам подгрузка изображений видна в редких случаях.
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  </head>
  <body>
    <h1>Страница с предзагрузкой изображений</h1>
      <p>содержимого страницы которое может содержать в себе всё что
      угодно кроме предзагружаемых изображений. Предзагружаемые изображения
      использоватьб здесь нет смысла тк эти изображения могут загрузиться
      дважды.</p>

      <ol>
        <li>Первый раз как используемые на этой странице</li>
        <li>Второй раз как предзагружаемые изображения</li>
      </ol>

      <p>Крайне желательно чтобы эта сраница использовалась
      продолжительное время, тк в противном случае предзагрузка может
      отработать не полностью. Если у пользователя в добавок ко всему отключен
      кэш то при переходе на следующую страницу браузер всёравно будет
      вынужден загрузить заново все изображения</p>

      <script type="text/javascript" src="preloadimg.js"></script>
      <script type="text/javascript">
      var srcArray= new Array(
        "/photo_com/650/3257.jpg",
        "/photo_com/650/3298.jpg",
        "/images/404_habra_error.png"
      );
      preloadImg(srcArray, "http://asha-city.ru");
      </script>
  </body>
</html>

* This source code was highlighted with Source Code Highlighter.


Возможности дальнейшей оптимизации
css — 700байт
далнешая оптимизация изображений — от 1%
Включение сжатия на уровне протокола вносит дополнительную нагрузку на CPU, это можно обойти как минимум двумя способами
1) — предварительное сжатие файлов, и раздача правильных заголовков. На сколько я понимаю в мире java это делается легко и без дополнительных издержек.
2) — Кэширование на прокси серевере или балансировщике нагрузки (nginx, haproxy, …)
Но это относится к нагрузочному тестированию и это уже совсем другая другая история, хоть и не менее увлекательная. Там есть свои инструменты, свои колоссальные проблемы и интереснейшие решения :)

ps: Ссылку на оптимизированный сайт пока не дам, находится в стадии разработки и многое на нём меняется.
pps: повторная загрузка изображений была связанна с временным глюком S3, — видомо обновляли софт и у них это получилость не так как ожидалось — проблема наблюдаласть часов 6 и именно в тот момент когда изучался вопрос что и как оптимизировать.
+32
13 октября 2009, 12:04
100

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

+2
DZhon #
Интересно! :) Благодаря Вашему посту открыл для себя GWT. Раньше не знал, что есть такая замечательная библиотека. Смотрю теперь на Web иначе.
+4
sidney3172 #
это очень странно потому что GWT уже долго есть, и пиарится достаточно не плохо самим гуглом…
0
DZhon #
Да это моя зеленость сказывается :) Надо же с чего-то начинать.
+2
RomanNikitin #
Помимо сжатия можно попробовать правильные хедеры выставлять статичным файлам (304 Not Modified) — js, css, картинкам.
Существенно снизит трафик (и сэкономит деньги на cloudfront) и ускорит повторную загрузку.

По поводу кэширования — есть забавный способ кэшировать через css но я не до конца уверен, во всех ли браузерах он работает:

.b-cache {
background: url(image1);
background: url(image2);
background: url(image3);
background: url(image4);
background: none;
}

Вечером сегодня протестирую этот способ.

В остальном всём кстати очень может помочь плагин Google Page Speed.
+1
opeg #
По поводу 304, у амазона это автоматически сделано. На Tomcat для статических файлов 304 работает по умолчанию. У Apache 2.2.9-10+lenny4 тоже 304 при повторной закачке.

По поводу кэширование через background — на сколько мне известно это хороший способ при небольшом количестве картинок.
При большом количестве картинок всплывают некоторые особенности
1) Невозможно остановить закачку
2) Невозможно контролировать количество потоков(прибито гвоздём в браузере)
Как следствие это может вызвать проблемы при большом количестве файлов(600 файлов — 10Мб).

Например все выделенные потоки для данного домена у браузера заняты, и запросы посланные js будут поставлены в очередь. В то время как картинки могли бы и подождать 0,01 секунды. А получается что будет ждать пользователь тк ресурсы браузера исчерпаны.

У нас эта проблема решена 2раза :)
1) разнос статики и динамики на разные сервера (статика у Амазона)
2) сокращение конкурирующих потоков в канале на стороне пользователя, чрез контролирование количества потоков прелоадера

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

В приведённом кусочке js есть неявная возможность контролировать количество потоков. Изменив количество вызовов функции cacheImage(); в 8-ой строке.
+2
tsmar #
«могущество java технологий создаваемых десятками тысяч гениальнейших программистов уже второе тысячелетие подряд» — я что-то пропустил в учебнике по истории? :)
0
Steward #
я тоже улыбнулся когда прочитал :)))
автор просто не совсем точно выразился — надо было написать:
«могущество java технологий создаваемых десятками тысяч гениальнейших программистов уже в двух тысячелетиях подряд»
ну или как-то тк — потому что эта фраза мне тоже не очень нравится :)))
0
opeg #
Вобщем-то нет ))
Конец прошлого и начало этого — итого: второе подряд
0
tsmar #
согласен, а в целом вполне себе полезное чтиво, если не учитывать, что каждый считает своим долгом самому проводить тесты по оптимизации :) от себя спасибо за лишний час жизни, не потраченый на yuicompressor.
0
opeg #
Здесь надо обратить на ключевую фразу «файла прошедшего через обфускацию средствами GWT», те если скрипт рукописный то он возможно очень сильно поможет
0
kurokikaze #
Ну Java же не на пустом месте возникла :) А гениальные Java-программисты наверняка были и до её появления — только проявить себя не могли :)
+2
bolk #
+2
mdevils #
Вы решили показать пример того как не надо писать код? with не рекомендуемый зачем-то.
В самой статье довольно сумбурный ход мыслей.
–2
opeg #
беспользный комент, хотя возможно и отражет сложившуюся ситуацию
Вы забыли обозначить ошибки, по этой причине я не могу вам аргументированно ответить или исправить ошибку
+1
mdevils #
Вместо системного последовательного подхода у вас какой-то метод народного тыка, который случайно привел к каким-то сомнительным результатам, которые так же сложно оценить не имея того, с чем можно сопоставить и к чему стремились.
+3
forgotten #
Это обходилось через вставку анонимной функции в onload и onerror которая вызывала родительскую функцию, те получалась рекурсия не позволяющая высвободить уже неиспользуемую память. Это проявилось в IE через ошибку «out of memory».

Вы про attachEvent/addEventListener не слышали?
А зачем массив с картинками в глобальную область видимости класть?
А with(img) зачем использовать?
Всем, кто начинает изучать Javascript: вот отличный пример того, как НЕ НАДО делать.
0
TheShock #
А with(img) зачем использовать?

Все про это говорят, но я так и не понял: чем плох with? По-моему — вполне даже ничего.
+2
forgotten #
Тем, что with работает совсем не так, как, очевидно, предполагает автор. Оператор with изменяет правила разрешения имен, что может приводить к крайне нетривиальным коллизиям, а не просто дает доступ к полям объекта.
См. books.google.ru/books?id=xn5aJpEJSEYC&lpg=PP1&ots=FK-RQ9KMPz&dq=flanagan%20javascript&pg=PA99#v=onepage&q=&f=false, глава 6.18
0
sunnybear #
1) отрицательно сказывается на производительности (виртуальной машине приходится заводить выделенное пространство имен)
2) не дает возможность корректно разрешить логику скрипта для внешних анализаторов (в частности, тот же YUI Compressor просто отказывается имена переменных в таких скриптах заменять)
3) Ничем не лучше (в данном случае и в общем) использования закэшированных переменных.

Собственно, все это ведет к тому, что with считается таким же моветоном, как и eval
0
opeg #
Вы про attachEvent/addEventListener не слышали?

Если я правильно понимаю документацию, и моя документация не устарела то этот подход не позволяет освободить память от предыдущего контекста, как следствие out of memory остаётся в силе
А зачем массив с картинками в глобальную область видимости класть?

fixed
А with(img) зачем использовать?

fixed
Всем, кто начинает изучать Javascript: вот отличный пример того, как НЕ НАДО делать.

что-то ещё :)
0
sirus #
попробуйте duris.ru, все картинки автоматически предзагружаются за один запрос ;)
0
opeg #
здорово, но помоему это немного не то :)
0
sunnybear #
10 Мб? O_o
0
sirus #
а почему бы и нет :), можно разбить на части. ну не АЯКСом их грузить, мне кажется это слишком, я хоть и ярый fullajax-er, но указанная реализация нерациональна, хотя тоже имеет право на жизнь.
0
sunnybear #
я ниже описал выход. Просто конкретно DURIS здесь может быть упомянут как подход. С тем же успехом можно упомянуть про Web Optimizer — ибо в нем тоже есть data:URI + mhtml + разделение файлов :)
0
sirus #
ну почему только же как подход и как решение :), Web Optimizer заточен под PHP, в данном случае его трудно применить
0
sunnybear #
отличная статья. Показательная. На тему того, как НЕ надо решать проблемы, но как они решаются в 99% случаях :)

Обычно, если не знают, как справиться с проблемой, то читают фундаментальные основы (например, той же клиентской оптимизации). Выясняют, как работает Tomcat. Выясняют, какая выгода от конкретных методик и приемов. А потом выбирают наиболее действенные и начинают их использовать. Здесь же был обратный подход: у нас есть непонятная в решении проблема, давайте ее бить всем, что под руку попадется — авось, сработает. Ну да, с пятого раза сработало. Повезло :)

По поводу картинок: 9Мб / 600 ~= 15 Кб. Если у вас на странице заканчиваются потоки (а при таком объеме они 100% будут заканчиваться), то реально стоит смотреть в сторону решений а-ля DURIS — через data:URI (mhtml) объединяем картинки в чанки (по 100Кб, например, которые еще и архивироваться умеют, общие потери на размер = 5-10%, выигрыш от канала +50%), затем на каждую страницу выливаем свое количество чанков (через файлы стилей, например).

Может быть, также сильно помогут множественные хосты: не увидел этого в заметке — они используются?
0
opeg #
отличная статья. Показательная. На тему того, как НЕ надо решать проблемы, но как они решаются в 99% случаях :)

Обычно, если не знают, как справиться с проблемой, то читают фундаментальные основы (например, той же клиентской оптимизации). Выясняют, как работает Tomcat. Выясняют, какая выгода от конкретных методик и приемов. А потом выбирают наиболее действенные и начинают их использовать. Здесь же был обратный подход: у нас есть непонятная в решении проблема, давайте ее бить всем, что под руку попадется — авось, сработает. Ну да, с пятого раза сработало. Повезло :)

Я забыл сказать что я администратор :), и с Томкатом немного знаком. Правда больше приходилось работь с Apache 1.3 те больше работал с C/C++ программами. Сейчас же преключаюсь на Java
По выгодам я вроде показал где и от чего сколько, если вы с чем-то несогласны я готов изучить этот вопрос и внести изменения или конструктивно ответить.

По поводу картинок: 9Мб / 600 ~= 15 Кб. Если у вас на странице заканчиваются потоки (а при таком объеме они 100% будут заканчиваться), то реально стоит смотреть в сторону решений а-ля DURIS — через data:URI (mhtml) объединяем картинки в чанки (по 100Кб, например, которые еще и архивироваться умеют, общие потери на размер = 5-10%, выигрыш от канала +50%), затем на каждую страницу выливаем свое количество чанков (через файлы стилей, например).

Спасибо за разъяснение, эта часть очень полезна и я её обязатьельно изучу. К соожалению высказывание автора выше не было стольже понятным.

Может быть, также сильно помогут множественные хосты: не увидел этого в заметке — они используются?

Да такое есть и встатье есть упоминание.
0
sunnybear #
я к тому, что подход просто неправильный показан. Gzip дает выигрыш в 80%. После него стоит жать YUI / JSMin скрипты и CSS Tidy / YUI стили. Но выигрыш в этом случае будет не больше 5-8%. 800Кб * 0,05 = 40 Кб. Естественно, что более действенным методом оказался выброс неиспользуемых скриптов. Но это работает далеко не всегда (и советовать выбрасывать неиспользуемую функциональность вредно: это ведет ко всяким «урезанным» версиями jQuery / Mootools и т.д.). Хотя куда проще взять тот же Sizzle / YASS, прикрутить к нему пара реально нужных модулей и запустить все это в продакшен.

Далее. Тема «нагрузки на сервер от сжатия» совершенно не раскрыта. Я так понимаю, что Java — это backend? Тогда скрипты и стили можно замечательно жать при деплое, а сам Amazon (я более чем уверен) может gzip-ипить самостоятеьно. Или у вас запросы напрямую к Tomcat для HTML-динамики? Тогда стоило упомянуть про альтернативные методы, типа minify — когда мы из HTML-кода выбрасываем все, причем именно в момент деплоя рабочей версии на рабочий сервер, чтобы «на лету» этим не заниматься.

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

Я могу долго так продолжать. Просто мне грустно, что микроскопом гвозди забивают. Что экономят: сначала работодатели, не желающие решать задачи с помощью тех сотрудников, которые для этого предназначены, например, клиентских архитекторов; а затем и сами сотрудники, потому что сроки поджимают, потому что попалась «новая интересная задача», потому что такой подход к самообразованию — неструктурированный. Грустно от того, что независимо от количества информации на тему клиентской оптимизации (сотни, если уже не тысячи статей, несколько полноценных книг, десятки докладов) все равно 90% разгона будет осуществляться именно так, «на коленке», на скорую руку, чтобы только работало. А что это не масштабируемо, что это будет не актуально через год, например. Что это, ускоряя в одном месте, будет замедлять в другом — никого не волнует.

Просто грустно.
0
egorinsk #
> Хотя куда проще взять тот же Sizzle / YASS

А я вот считаю, что полноценная машина селектров редко когда нужна (ообенно свойства типа :nth-child), по моему так проще написать пару своих функций типа findByClass(), findFirstChild() (ессно с поддержкой штук типа getByClassName/querySelectorAll, если они есть в браузере), этого хватает в 90% случаев, а код намного лечге и быстрее.

0
sunnybear #
собственно YASS по такой технологии и написан. Вы бы ознакомились что ли
0
egorinsk #
Нет, не по такой. Я пишу, что мне достаточно часто только поиска по имени класса/тега, без поддержки сложных селекторов, и уж тем более без истемы динамической загрузки яваскрипт-файлов с зависимостями (хотя конечно иногда это может и пригодиться).
0
sunnybear #
CSS1-ветка — это именно то, что Вы описываете. Я что-то упустил?
0
egorinsk #
Может, я не ясно выразился. Мне хватает поиска по таким селекторам: tag, .class и tag.class. Про ветку css1 я не знал, но даже там строка для поиска парсится, а в моем случае парсер просто излишен.
0
opeg #
я к тому, что подход просто неправильный показан. Gzip дает выигрыш в 80%. После него стоит жать YUI / JSMin скрипты и CSS Tidy / YUI стили. Но выигрыш в этом случае будет не больше 5-8%. 800Кб * 0,05 = 40 Кб. Естественно, что более действенным методом оказался выброс неиспользуемых скриптов. Но это работает далеко не всегда (и советовать выбрасывать неиспользуемую функциональность вредно: это ведет ко всяким «урезанным» версиями jQuery / Mootools и т.д.). Хотя куда проще взять тот же Sizzle / YASS, прикрутить к нему пара реально нужных модулей и запустить все это в продакшен.


По этому поводу написано, и даже приведён листинг. В моём случае при использовании yui размер увеличился. Подробности в тексте.

Далее. Тема «нагрузки на сервер от сжатия» совершенно не раскрыта. Я так понимаю, что Java — это backend? Тогда скрипты и стили можно замечательно жать при деплое, а сам Amazon (я более чем уверен) может gzip-ипить самостоятеьно. Или у вас запросы напрямую к Tomcat для HTML-динамики? Тогда стоило упомянуть про альтернативные методы, типа minify — когда мы из HTML-кода выбрасываем все, причем именно в момент деплоя рабочей версии на рабочий сервер, чтобы «на лету» этим не заниматься.

1) Да можно жать, на эту тему есть в статье заметка, в конце
2) Амазон не жмёт контент, но позволяет пользователю сжать, закачать и выставить соответствующие заголовки. И этот момент я действительно не упоянул.
3) Статика хранится на S3 динамика на Tomcat. К Tomcat идут только rpc запросы и там хранятся файлы который изменются при обновлениях. Например js (с очень большой вероятностью это в дальнейшем изменится). Я действитель забыл на это указать. И это важный момент.
— про minify почитаю

Я могу долго так продолжать. Просто мне грустно, что микроскопом гвозди забивают. Что экономят: сначала работодатели, не желающие решать задачи с помощью тех сотрудников, которые для этого предназначены, например, клиентских архитекторов; а затем и сами сотрудники, потому что сроки поджимают, потому что попалась «новая интересная задача», потому что такой подход к самообразованию — неструктурированный. Грустно от того, что независимо от количества информации на тему клиентской оптимизации (сотни, если уже не тысячи статей, несколько полноценных книг, десятки докладов) все равно 90% разгона будет осуществляться именно так, «на коленке», на скорую руку, чтобы только работало. А что это не масштабируемо, что это будет не актуально через год, например. Что это, ускоряя в одном месте, будет замедлять в другом — никого не волнует.

Очень хорошо. Пределов совершенству нет. Я внимательно читаю.
Это из раздела экономики и ограниченности ресурсов. Я незнаю лучшего пути и если Вы его предложете я готов по нему пойти :)
По поводу мастабируемости можно по подробнее.
Замедление в другом месте(сжатие на коннекторе) сейчас наиболее дёшево, и через год это станет не актуальным. По одной из 2х причин.
1) Эта установка будет стоять за кэширующим балансировщиком (он закэшируетс файлы с расширением js, html, xml, ..., как следствие сжатие на коннекторе будет производиться один раз)
2) Это будте сделано средствами приложения (в моём понимании на этом этапе это не требуется, тк есть более важные задачи и ограниченные ресуры)

«невешать нос Гардемарины… » :)
–1
sunnybear #
проблема в том, что я уже иду по лучшему пути. И, возможно, смогу доказать через год-другой Вашему менеджеру, что текущий путь не верен и текущий подход не применим. И что на Ваших услугах можно сэкономить. Потому что считаю, что производительностью должны заниматься профессионалы. И стоить это должно копейки (или даже бесплатно). Как это совместить — уже другой, намного более интересный вопрос :)
0
opeg #
К сожалению хабрапочта работает через раз, и отправить в личку не удалось.

Готов дать Вам контакты моего руководства прямо сейчас, и я не беспокоюсь остаться без работы. Моя работа станет ещё более интересной и насыщенной.

С уважением к Вам и вашим трудам.
зы: оч жаль что не вличку
0
Vii #
Хотя куда проще взять тот же Sizzle / YASS, прикрутить к нему пара реально нужных модулей и запустить все это в продакшен.

С другой стороны, в последствии когда придется (из жизненного опыта говорю) дорабатывать/расширять функционал проекта, такая экономия приводит в основном к изыбретению большого количества костылей: уже есть достаточно увесистый кусок кода базирующийся на некой легковесной библиотеке (а то и самопальной недобиблиотеке-lite-0.3-alpha :)), старых возможностей не хватает, а прикрутить универсальный jQuery (Mootools, пр.) уже как-то не к селу, не к городу.
0
garbuz #
Как раз недавно тоже столкнулись с проблемой производительности в проекте. Страница грузилась конечно не 1,5 минуты, ну а секунд 30-35. Приложение построено на WebSphere Portal и java-технологиях. Сделали почти тоже самое, кроме предзагрузки изображений.
— кэширование стратики на сервере
— оптимизация изображений
— компрессия js и css
— перенос картинок на другой хост

–3
egorinsk #
700 Кб яваскрипта?? Ничего личного, но по моему, фигня ваш проект, с точки зрения качества, а яваскрипт надо писать ручками, а не генерировать кодогенераторами. И да, я не люблю Яву, и чрезмерное использвоание стороннего кода, как выясняется не зря :)
0
fedor7 #
Спасибо!

Всю статью пока не осилил :))
Но за это отдельное спасибо:
Оптимизация проводилась со знанием и пониманием
www.artlebedev.ru/tools/technogrette/img/
НЛО прилетело и опубликовало эту надпись здесь
0
opeg #
Спасибо, очень полезная ссылка
+1
ItGold #
Передайте привет вашим Java программистам:
GWT Image Bundles
+1
opeg #
Спасибо )

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