Проблемы с производительностью HTML5 Canvas в некоторых мобильных браузерах.

Привет у меня есть веб-приложение, которое должно быть в состоянии работать как на смартфоне, так и на настольных браузерах. Хотя я ожидал получить любопытное поведение на небольших устройствах, таких как Iphone, я был уверен, что он будет хорошо работать на вкладке Android Galaxy, которая является Android-устройством, с которым я могу запускать тесты на данный момент.

теперь я установил кучу браузеров на вкладке Galaxy, чтобы проверить вещи с:

  • Родном Android Браузер
  • Chrome для Android
  • Firefox для Android

на рабочем столе я использую

  • в Firefox
  • Google Chrome

и, наконец, у меня есть iPhone для тестирования.

веб-сайт использует HTML5 canvas для пиксельного и спрайтового рисования без причудливых преобразований, фильтров или эффектов, в основном простых путей и полигонов. Я слушаю сенсорные события и использую requestAnimationFrame для правильного перерисовка.

в целом приложение хорошо работает в настольных браузерах, оно также отлично работает на iOS Safari (iPhone) и Firefox-on-Android. Тем не менее, родной браузер андроидов дает мне проблемы. Я настроил его так, что экран краснеет, когда javascript не реагирует, и он почти всегда мигает при касании экрана.

поэтому мне интересно, есть ли какие-либо известные проблемы с Android Native App и HTML5. Из-за несуществующего имени родного браузера его довольно трудно google информацию об этом. любые идеи, где я могу получить больше информации? Есть идеи, что может вызвать отставание родного браузера Android?

есть несколько идей по этому вопросу:

  • iOS не поддерживает requestAnimationFrame, поэтому я заменил его заменой на основе тайм-аута. Если я использую эту замену в родном браузере Android, проблема сохраняется.

  • Я использую AJAX (google clojure xhrio) довольно регулярно извлекает данные с сервера. Может быть, обратные вызовы поиска данных забивают мой конвейер событий?

  • являются сообщениями консоли журнала (console.log) известно, чтобы замедлить приложения? Могут ли они запустить браузер для повторного запуска через дерево DOM или что-нибудь связанное?

2 ответов


я провел много экспериментов с canvas во многих браузерах. Некоторые проблемы с производительностью, которые я заметил:

во-первых, о вашем гадать:

  • , когда requestAnimationFrame поддерживается браузером, материал для рисования и само приложение более отзывчивы. Использовать setTimeout или setInterval как запасной вариант всегда возможен, но вы должны быть осторожны, о сроках. Это робастный polyfill может немного помочь, но ничего по сравнению с родным метод requestAnimationFrame.

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

    if(typeof console === "undefined"){ console = {}; }

  • для интенсивных приложений в реальном времени веб-сокеты быстрее, чем http-запросы. К сожалению, это функция не поддерживается старыми родными браузерами android. Если невозможно использовать веб-сокеты, следует минимизировать http-запросы.

Примечание: Chrome для поддержки android большинство функций HTML5 приведены здесь, в том числе requestAnimationFrame и websockets.

дополнительная информация:

  • рисование текста с использованием контекста 2d fillText это слишком дорого, но в некоторых браузерах это еще хуже. Сделать ваши тексты в другой холст или использовать растровые шрифты. (В родном браузере Android, после замены filltext рисование для предварительного рендеринга, производительность выросла с 10-15 FPS до 30-45 FPS в некоторых играх, которые я сделал).

  • избегайте масштабирования и поворота контекста, потому что они также вызывают падение производительности. Если вам нужно масштабировать или поворачивать спрайт только один раз, используйте pre-render.

  • вам нужно уменьшить чертеж в реальном времени. Подготовьте свой материал, когда сможете. Перерисуйте только то, что изменилось и нуждается в обновлении.

  • попробуйте написать эффективная память и дружелюбный код сборщика мусора.

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

совет: сделать некоторые стресс-тесты для функций, которые вы не уверены, если они убийцы производительности и захватить результаты тестов.

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

для получения дополнительной информации перейдите по ссылкам ниже:

также поиск производительности в посты & Уроки.

EDIT
Это jsfiddle код показывает некоторые вещи, охваченные в этом ответе, и предоставляет грубый счетчик fps для сравнения. Отредактируйте эту скрипку самостоятельно и проверьте ее.


в зависимости от того, что вы рисуете, наиболее распространенная стратегия повышения производительности с HTML5 canvas-использовать слои (т. е. несколько холстов) и обновлять только слои, которые нужно перерисовать, а не перерисовывать все это на каждом кадре анимации. Вы можете свернуть что-то подобное самостоятельно, или вы можете использовать что-то вроде http://www.concretejs.com/ что облегченная структура холста Html5 которая включает периферийные вещи как обнаружение удара, наслаивая, кэширование, поддержка соотношения пикселей, загрузки и т. д. Вы бы сделали что-то вроде этого:

var wrapper = new Concrete.Wrapper({
  width: 500,
  height: 300,
  container: el
});

var layer1 = new Concrete.Layer();
var layer2 = new Concrete.Layer();

wrapper.add(layer1).add(layer2);

// something happens which requires you to redraw layer2, but not layer1...
layer2.sceneCanvas.context.fillStyle = 'red';
layer2.sceneCanvas.context.fillRect(0, 0, 200, 100);