Каков наилучший способ циклически проходить большое количество изображений с фиксированной позицией в WebKit? - PullRequest
6 голосов
/ 15 декабря 2011

В настоящее время я работаю над небольшим сайтом для моей семьи.Одна из вещей, которые я хотел сделать, - это сделать базовое видео для «стоп-движения».Я мог собрать его и загрузить в Vimeo или что-то в этом роде, но я подумал, что это прекрасная возможность использовать только HTML, CSS и Javascript.

У меня все стилизовано, и мой JS работает и т. Д.кроме того, что это ужасно работает в Chrome и Safari.Интересно, что он отлично работает в Firefox, и я пока не поддерживаю его в IE.Я надеюсь от 8 до 12 кадров в секунду при воспроизведении музыки, которую я пока не удосужился попробовать из-за этого.Плохая производительность - это нечто меньшее.В настоящее время я получаю примерно 3 fps в Firefox ( приемлемо , но не то, что я искал), а в Chrome и Safari я получаю примерно .6795 fps.

При запускеChrome Profiler, я получаю следующий (соответствующий) вывод.

99.96%   99.96%     (program)
0.03%    0.03%      (garbage collector)
0.01%    0.01%      script.js:5:nextSlide

Я никогда раньше не использовал Profiler, но я полагаю, это показывает мне, что мой JS - это не то, что так сильно сказывается на производительности.

Я опубликовал тестовую страницу , в которой документируются различия в производительности, которые вы можете посетить с помощью Chrome и Firefox.

Я также обнаружил, что это, похоже, связано сизображения зациклены. Зацикливание разных, более простых изображений , кажется, прекрасно работает как в Chrome, так и в Firefox, несмотря на то, что Chrome по-прежнему требует немного больше энергии, чем Firefox.

Как еще одно доказательство этогоВывод, хотя и совершенно неприемлемый, демонстрируется здесь , после запуска изображений через convert -compress JPEG -quality 1.Они работают гораздо эффективнее, но, конечно, качество ужасное.

Я запустил эти тестовые страницы в Chrome (16.0.912.63), Safari (5.1.2 (6534.52.7)), WebKit ночью (Version 5.1.2 (6534.52.7, r102985)) иMobile Safari (latest as of 2011/12/28) и только Mobile Safari работает так же хорошо, как FireFox.Настольные браузеры были протестированы на MacBook Pro.

2.7 GHz Intel Core i7
8 GB 1333 MHz DDR3

Интересно, что Mobile Safari на iPad 2 работает так же хорошо, как FireFox при рендеринге тестовой страницы .Хотя Mobile Safari основан на WebKit, в этом случае он работает совершенно иначе.

Уменьшение вызова setTimeout на 144 с 244 также, похоже, ничего не делает.В этот момент я пришел к 244 совершенно произвольно, так как на раннем этапе стало ясно, что время отображения по сравнению с вызовом, похоже, не соответствует почти напрямую.Это заставляет меня поверить, что я показываю слайд-шоу так быстро, как только могу в каждом браузере.

Итак, мой вопрос, как я могу сделать этот исполнитель в WebKit?

Ответы [ 8 ]

12 голосов
/ 02 января 2012

Вы можете отладить производительность страницы в Chrome, используя вкладку «Таймлайн» в инструментах разработчика Chrome. Проблема с вашим сценарием в том, что ваш цикл перерисовки слишком дорогой, в настоящее время перерисовка каждого кадра занимает 1,35 с.

enter image description here

Плохая производительность не имеет ничего общего с качеством изображений JPEG (хотя качество изображения также влияет на время рендеринга страницы). Проблема в том, что вы обновляете z-index, в результате чего Chrome перерисовывает все изображений вместо следующего кадра (у вас есть O (n) веб-сайт слайдера изображений!).

Браузеры пытаются выполнить минимально возможные действия в ответ на изменение, например: изменение цвета элемента приведет только к перекрашиванию элемента.

Изменение свойства z-index элемента в основном аналогично удалению узла из дерева и добавлению в него другого узла. Это приведет к разметке и перерисовке элемента, его дочерних элементов и, возможно, родных элементов. Я предполагаю, что в Chrome перерисовываются братья и сестры, это объясняет ужасную производительность.

Чтобы устранить эту проблему, нужно обновить свойство opacity вместо z-index. В отличие от z-index, opacity не изменяет дерево DOM. Это только говорит рендеру игнорировать этот элемент. Элемент все еще «физически» присутствует в DOM. Это означает, что перекрашивается только один элемент, а не все братья и сестры и дети.

Это простые изменения в вашем CSS должны помочь:

.making-of .slide#slide-top {
   opacity: 1;
   /* z-index: 5000; */
}


.making-of .slide {
   position: fixed;
   /* z-index: 4000; */
   opacity: 0;
   ....
}

И вот результат: перекраска перешла с 1,35 до 1 мс:

enter image description here

EDIT:

Вот jsfiddle, использующий решение для непрозрачности, я также добавил CSS3 переходы (просто для удовольствия!)

http://jsfiddle.net/KN7Y5/3/

Подробнее о том, как работает рендеринг в браузере:

http://www.html5rocks.com/en/tutorials/internals/howbrowserswork/

5 голосов
/ 02 января 2012

Я посмотрел код на вашем сайте и обнаружил две вещи, которые ограничивают скорость.

1) В JavaScript время ожидания составляет примерно 1/4 секунды (244 миллисекунды).Это означает, что ваша лучшая частота кадров составляет около 4 кадров в секунду (кадров в секунду).Это можно исправить, просто уменьшив задержку, чтобы она соответствовала частоте кадров, которую вы на самом деле хотите. Я вижу, что ваше последнее редактирование затрагивает этот вопрос, но я не хотел игнорировать его, поскольку в конечном итоге это крайне важно для достижения более высокой частоты кадров, которую вы хотите .

2)Вы используете z-index для управления тем, какое изображение видно.В общем случае обработка z-index позволяет упорядочивать объекты, которые имеют разные размеры и позиции, чтобы вы могли контролировать, какой объект виден в местах, где два или более объектов перекрываются.В вашем случае все объекты отлично перекрываются, и подход z-index работает отлично, за исключением одной главной проблемы: браузеры не оптимизируют обработку z-index для этого случая, и поэтому они фактически обрабатывают каждое изображение на каждомрама .Я подтвердил это, создав модифицированную версию вашей демонстрации, в которой использовалось вдвое больше изображений - FPS был уменьшен почти в 2 раза (другими словами, для отображения всего набора потребовалось в 4 раза больше времени).

Я взломал альтернативный подход, который достиг гораздо более высокого FPS (60 или более) как в Chrome, так и в Firefox.Суть в том, что я использовал свойство display вместо манипулирования z-index:

.making-of .slide#other {
   display: none;
}

.making-of .slide#slide-top {
   display: inline;
}

и JavaScript:

function nextSlide() {
  ...
  topSlide.id='other';
  nextTopSlide.id='slide-top';
  ...
  setTimeout(nextSlide, 1);
  ...
}

Я также внес некоторые изменения в HTMLВ частности, включая id="other" в тег для каждого изображения.


Так почему же WebKit такой медленный? Как указывалось в других комментариях, очень низкая производительность, котораявы видите на Webkit, похоже, для Mac.Мое лучшее предположение об этом заключается в том, что версия WebKit для Mac на самом деле не использует «турбо» версию libjpeg (несмотря на то, что она указана в титрах).В вашем тесте декомпрессия JPEG вполне может быть стробирующим фактором, если она фактически распаковывает каждое изображение в каждом кадре (как, вероятно, имеет место). Сравнительный анализ libjpeg-turbo показал примерно пятикратное улучшение скорости декомпрессии.Это примерно соответствует разнице, которую вы видите между Firefox и Chrome (3 FPS против 0,6795 FPS).

Дополнительные сведения о libjpeg-turbo и о том, как эта гипотеза объясняет некоторые другие ваши результаты, см. мой другой ответ .

1 голос
/ 30 декабря 2011

Случайное предположение: ускорение GPU. Это зависит от устройства, и сейчас среди браузеров большая гонка.

Вы можете попробовать более позднюю версию Chrome, такую ​​как канарейки, http://tools.google.com/dlpage/chromesxs (сейчас 18.х), просто чтобы получить больше данных.

about: версия в Chrome должна содержать версию WebKit.

Кроме того, вы пробовали существующие решения для слайд-шоу, такие как http://jquery.malsup.com/cycle/? Интересно, узкое место здесь играет с z-индексом ... может быть, помогло бы отображать только 1-2 изображения (все остальные с использованием display: none). Это опять догадка.

1 голос
/ 29 декабря 2011

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

0 голосов
/ 03 января 2012

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

0 голосов
/ 29 декабря 2011

Я тестировал его в опере, и он работал чертовски медленно, я заметил, что опера поставила в очередь более 150 изображений для загрузки, может стоить попробовать скачать ~ 20 одновременно?

0 голосов
/ 28 декабря 2011

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

Если вы используете Linux, я ранее использовал инструмент сжатия JPEG http://linuxpoison.blogspot.com/2011/01/utility-to-optimize-compress-jpeg-files.html. Это не вредит качеству, как пример, который вы привели в ImageMagick.

Также http://trimage.org/ имеет поддержку JPG и будет моей первой рекомендацией!

Если вы работаете в Windows, может быть что-то вроде этого: http://www.trans4mind.com/personal_development/convertImage/index.html

Я не тестировал метод Windows, и я даже не уверен, что он поддерживает пакет

Надеюсь, это поможет!

P.S. Для PNG я иногда использую http://pmt.sourceforge.net/pngcrush/ вместе с http://trimage.org/

или без него *
0 голосов
/ 28 декабря 2011

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

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

Вы сказали, что улучшили скорость Chrome, значительно снизив качество или сложность ваших изображений.Это может быть объяснено тем фактом, что для областей с очень низкой детализацией алгоритм распаковки JPEG может обойти большую часть работы, которую он обычно должен выполнять.Если фрагмент пикселей 8x8 можно уменьшить до одного цвета, декомпрессия этого фрагмента становится очень простой задачей.

В этой статье Википедии содержится дополнительная информация и источники.Это говорит о том, что Chrome версии 11 имеет новую библиотеку.Вы можете ввести « chrome: // credits » в строке местоположения и посмотреть, ссылается ли оно на « libjpeg-turbo ».«libjpeg» - оригинальная библиотека, а «libjpeg-turbo» - оптимизированная версия.

Еще одна возможность заключается в том, что libjpeg-turbo не поддерживается в Webkit на Mac (хотя я не знаю, что именно).Есть подсказка о том, почему это может быть опубликовано здесь .

PS. Вы можете получить лучшую скорость декомпрессии, сжимая с помощью другого алгоритма, такого как PNG (хотя ваши коэффициенты сжатия будутскорее всего пострадает).С другой стороны, может быть, вам стоит использовать HTML5 видео , возможно, с WebM форматом .

...