Опубликован: 16.06.2010 | Доступ: свободный | Студентов: 2352 / 93 | Оценка: 4.39 / 4.00 | Длительность: 17:32:00
ISBN: 978-5-9963-0253-6
Лекция 7:

Технологии будущего

6.7. Вычисляем при помощи Web Workers

Данный раздел написан под впечатлением статьи Джона Ресига "Computing with JavaScript Web Workers" (http://ejohn.org/blog/ web-workers/), в которой он раскрыл особенности встроенного в браузеры механизма "отложенных" вычислений при помощи JavaScript и его будущие перспективы.


Последняя спецификация Web Workers, несомненно, является наиболее перспективной из грядущих нововведений в браузерах, которая позволяет исполнять JavaScript-задачи параллельно, не блокируя интерфейс браузера.

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

Имея в виду текущее положение вещей, давайте углубимся в спецификацию Web Workers.

6.7.1. Web Workers

Рекомендация Web Worker (http://www.whatwg.org/specs/web-workers/ current-work/) частично основывается на уже проделанной работе со стороны команды Google Gears относительно модуля WorkerPool (http://code.google.com/apis/gears/api workerpool.html). Это идея существенно выросла и была значительно доработана, чтобы стать рекомендацией.

Worker — это скрипт, который может быть загружен и исполнен в фоновом режиме. Web Workers позволяют легко это сделать, например:

В этом примере будет загружен скрипт, расположенный по адресу worker.js, а его выполнение будет произведено в фоновом режиме (скорее всего, браузеры будут использовать встроенные средства операционной системы — нити — для реализации такого поведения).

Однако есть несколько серьезных "подводных камней":

  1. Worker не имеет доступа к DOM. Никакого document, getElementById и т. д. (Наиболее важными исключениями из этого правила будут методы setTimeout, setInterval и XMLHttpRequest.)
  2. У Worker нет прямого доступа к родительской странице.

Имея в виду эти ограничения, стоит сразу задаться вопросом: а для чего, собственно, может пригодиться Worker и какие задачи он способен решать?

Вы можете использовать Worker, обмениваясь с ним сообщениями. Все браузеры (которые поддерживают данную спецификацию) позволяют обмениваться строковыми сообщениями (Firefox 3.5 также поддерживает обмен JSON-совместимыми объектами). Сообщение может быть как отослано Worker, так и сам Worker может ответить родительской странице таким сообщением. Ниже приведен пример обмена сообщениями.

Обмен сообщениями производится при помощи API postMessage следующим образом:

var worker = new Worker("worker.js");
// Ждем сообщений от worker
worker.onmessage = function(e){
// Сообщение от клиента:
e.data;
};
worker.postMessage("start");
Клиент:
onmessage = function(e){
if ( e.data === "start" ) {
// Выполняем какие-нибудь вычисления
done();
}
};
function done(){
// Отправляем полученный результат на главную страницу
postMessage("done");
}

Это ограничение на передачу информации при помощи сообщений имеет под собой веские основания: оно позволяет безопасно запускать дочерний скрипт (потому что, к счастью, он не может повлиять на родительский) и защищает родительский поток (обеспечение безопасности для DOM от вторжения из других потоков превратилось бы в ночной кошмар для клиентских разработчиков).

Прямо сейчас Web Workers присутствуют в Firefox 3.5 и Safari 4. Они также заявлены в последних ночных сборках Chromium (http://build.chromium.org/buildbot/snapshots/chromium-rel-xp/ ). Наверное, большинство тут же подумают: что нам до возможности, которая доступна лишь для небольшой части веб-пользователей (только в двух современных браузерах!), — но это не должно быть проблемой. Web Workers позволяют эффективно использовать пользовательские машины для параллельных вычислений. В такой ситуации вы можете создавать две версии своих приложений (одну для старых браузеров, и одну — для запуска через механизм Web Workers при его наличии в браузерах). В новых браузерах это просто будет работать значительно быстрее.

Приведем некоторые занимательные примеры использования данного механизма, которые используют заявленное API.

6.7.2. Расчет освещения (RayTracing)

Расчет освещения при помощи Web Workers, источник ejohn.org

Рис. 6.14. Расчет освещения при помощи Web Workers, источник ejohn.org

Здесь Canvas применен для отрисовки рассчитанной сцены. Если включить Web Workers, то заметно, как картинка отрисовывается по частям. Это происходит благодаря разбиению всей работы на части и поручению каждого набора пикселей отдельному Worker. Этот Worker затем подает массив цветов для отрисовки на Canvas, а родительская страница их применяет. (Заметьте, сам по себе Worker ничего не изменяет.)

6.7.3. Отслеживание движения

Отслеживание движения при помощи Web Workers, источник: ejonh.org

Рис. 6.15. Отслеживание движения при помощи Web Workers, источник: ejonh.org

В этом случае применяется несколько технологий: элемент video, элемент canvas и отрисовка кадров видео на сам холст. Все отслеживание движения производится в фоновом режиме при помощи Web Workers (по- этому передача видео не останавливается и не блокируется).

6.7.4. Эмуляция огня

Эмуляция огня при помощи Web Workers, источник: ejohn.org

Рис. 6.16. Эмуляция огня при помощи Web Workers, источник: ejohn.org

Этот пример пытается ограничить несколько случайных точек, используя алгоритм эмуляции огня (simulated annealing). Также здесь приведено анимированное PNG-изображение (работает в Firefox 3.5), которое вращается, пока идет вычисление в фоновом режиме.

6.7.5. Вычисление при помощи JavaScript Web Workers

Недавно закончилось интересное соревнование от Engine Yard (http://www.engineyard.com/blog/2009/programming-contest-win-iphone-3gs-2k-cloud-credit/ ). Задание было следующим: необходимо было подобрать фразу, которая бы давала наиболее близкий к исходному SHA1LU, расстояние между хэшами вычислялось по Хэммингу (число отличающихся битов).

Наибольший интерес представляли два участника, которые попытались решить эту задачу при помощи JavaScript. Их программы запускались в браузере и использовали пользовательский компьютер для проведения вычислений. Скорее всего, никто из них так и не добился впечатляющего результата (если брать во внимание тех кластерных монстров, с которыми пришлось соревноваться), но сам подход вызывает неподдельный интерес.

В обоих случаях (если верить исходному коду) используется почти одна и та же тактика: рассчитываются несколько результатов, разделяемых по таймеру. Скорость подбора варьируется от браузера к браузеру на уровне 1000-1500 расчетов в секунду. Естественно, эти алгоритмы весьма ресурсоемки и полностью "убивают" пользовательский процессор и "замораживают" интерфейс браузера.

По-видимому, это является великолепной возможностью применить Web Workers!

Если взять реализацию Ray C Morgan (http://www.raycmorgan.com/), вырезать весь интерфейс и таймеры и разложить вычисления на 4 параллельных потока для Web Workers, то можно добиться скорости в 4500-9500 расчетов в минуту (в новых браузерах, которые поддерживают механизм Web Workers).

По этим ссылкам можно посмотреть на демонстрацию (автором которой является Джон Ресиг) и скачать исходные коды:

Ольга Артёмова
Ольга Артёмова

Доброго времени суток!

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

Сертификация: оптимизация и продвижение web-сайтов.

Наталья Алмаева
Наталья Алмаева
Россия
Вадим Барков
Вадим Барков
Украина, Киев