Web workers

2,404 views

Published on

Published in: Technology, Business
  • Be the first to comment

Web workers

  1. 1. Web Workers<br />(2011-04-21, Last Call Review Ended)<br />장현준<br />(iam@b4you.net)<br />㈜트루모바일<br />2011. 08. 18.<br />2011-08-18<br />1<br />
  2. 2. Contents<br />Web Workers 개요<br />Browser별지원 현황<br />Web Workers 특성및 용도, 종류<br />Object IDL<br />Samples<br />Web Workers 성능 향상 및 한계<br />2011-08-18<br />2<br />
  3. 3. Web Workers 개요<br />Background에서 동작하는 script<br />Thread와 유사한 개념<br />Main thread(UI thread)와 분리된 thread<br />Javascript에서 병렬 처리 가능<br />2011-08-18<br />3<br />
  4. 4. Web Workers 개요<br />기존의 방식 vs Web Workers<br />var timer = setInterval(doWork, 100);<br />...<br />function doWork() {<br /> // do something<br />}<br />// main.js<br />var worker = new Worker('worker.js');<br />worker.addEventListener('message', onMessage1);<br />worker1.postMessage(...);<br />// worker.js<br />self.onmessage = function(event) {<br /> // do something<br />};<br />2011-08-18<br />4<br />
  5. 5. Browser별 지원 현황<br />출처: http://caniuse.com/#search=worker<br />2011-08-18<br />5<br />
  6. 6. Web Workers 특성<br />모든 데이터는 JSON 형태로 송/수신됨<br />Object는 call-by-value로 전달<br />Channel messaging 방법 사용<br />postMessage()를 이용하여 데이터 송신<br />onmessage()를 통해 데이터 수신<br />2011-08-18<br />6<br />
  7. 7. Web Workers 특성<br />전역 변수/메서드<br />Worker는 전역 변수/메서드를 사용할 수 없음<br />전역 변수 등 공유 자원이 없으므로 Race condition이 발생 하지 않음<br />Mutex/Critical Section 등 불필요<br />SharedWorker는 전역 변수를 사용할 수 있음<br />한 번에 하나의 onmessage()만 호출 되므로 Race condition이 발생 하지 않음<br />Worker와 같이 Mutex/Critical Section 등 불필요<br />2011-08-18<br />7<br />
  8. 8. Web Workers 특성<br />Main(UI) thread와 분리<br />Worker 내부에서 UI 조작 불가능<br />(이론상으로)Worker 내의 연산은 Main thread에 영향을 미치지 않음<br />2011-08-18<br />8<br />
  9. 9. Web Workers 용도<br />긴 시간이 필요한 작업<br />AJAX<br />WebSocket<br />복잡한 산술계산<br />기타 등등<br />UI 갱신이 중요한 경우<br />UI가 non-blocking 되어야 하는 환경<br />2011-08-18<br />9<br />
  10. 10. Web Workers 종류<br />Worker<br />thread 생성<br />SharedWorker<br />공유 변수를 갖는 thread 생성<br />2011-08-18<br />10<br />
  11. 11. Worker IDL<br />[Constructor(in DOMStringscriptURL)]<br />interface Worker : AbstractWorker {<br /> void terminate();<br /> void postMessage(in any message, in optional sequence<Transferable> transfer);<br /> attribute Function? onmessage;<br />};<br />[Supplemental, NoInterfaceObject]<br />interface AbstractWorker : EventTarget {<br /> attribute Function? onerror;<br />};<br />[NoInterfaceObject]<br />interface Transferable { };<br />2011-08-18<br />11<br />
  12. 12. SharedWorker IDL<br />[Constructor(in DOMStringscriptURL, in optional DOMString name)]<br />interface SharedWorker : AbstractWorker {<br />readonly attribute MessagePort port;<br />};<br />interface MessagePort {<br /> void postMessage(in any message, in optional MessagePortArray ports);<br /> void start();<br /> void close();<br /> // event handlers<br /> attribute Function onmessage;<br />};<br />MessagePort implements EventTarget;<br />typedef sequence<MessagePort> MessagePortArray;<br />2011-08-18<br />12<br />
  13. 13. MessageEvent IDL<br />onmessage()의 첫 번째 인자<br />interface MessageEvent : Event {<br />readonly attribute any data;<br />readonly attribute DOMString origin;<br />readonly attribute DOMStringlastEventId;<br />readonly attribute WindowProxy? source;<br />readonly attribute MessagePort[] ports;<br /> void initMessageEvent(in DOMStringtypeArg, in booleancanBubbleArg, in booleancancelableArg, in any dataArg, in DOMStringoriginArg, in DOMStringlastEventIdArg, in WindowProxy? sourceArg, in sequence<MessagePort> portsArg);<br />};<br />2011-08-18<br />13<br />
  14. 14. Channel Messaging<br />two-way pipes<br />postMessage() / onmessage() 를 이용하여 구현<br />Web Workers에서 주로 사용되는 방식<br />MessageChannel<br />port1<br />port2<br />self.postMessage()<br />self.postMessage()<br />onmessage()<br />handler<br />onmessage()<br />handler<br />2011-08-18<br />14<br />
  15. 15. MessageChannel IDL<br />[Constructor]<br />interface MessageChannel {<br />readonly attribute MessagePort port1;<br />readonly attribute MessagePort port2;<br />};<br />interface MessagePort {<br /> void postMessage(in any message, in optional MessagePortArray ports);<br /> void start();<br /> void close();<br /> // event handlers<br /> attribute Function onmessage;<br />};<br />MessagePort implements EventTarget;<br />typedef sequence<MessagePort> MessagePortArray;<br />2011-08-18<br />15<br />
  16. 16. Channel Messaging Sample 1<br />// channel1.html<br />...<br />var channel = new MessageChannel();<br /> channel.port1.onmessage = function(event) {<br /> console.log(event.data);<br /> };<br /> channel.port2.postMessage([1, 2, 3]);<br />...<br />2011-08-18<br />16<br />
  17. 17. Channel Messaging Sample 2<br />// channel2.html<br />...<br />var channel = new MessageChannel();<br /> channel.port1.onmessage = function(event) {<br /> console.log("Channel1: " + event.data);<br /> };<br /> channel.port2.onmessage = function(event) {<br /> console.log("Channel2: " + event.data);<br /> };<br /> channel.port1.postMessage([1, 2, 3]);<br /> channel.port2.postMessage([4, 5, 6]);<br />...<br />2011-08-18<br />17<br />
  18. 18. Worker Sample 1<br />// worker1.html<br />...<br />var worker = new Worker("worker1.js");<br />worker.onmessage = function(event) {<br /> console.log("Received: [" + event.data + "]");<br /> };<br />...<br />// worker1.js<br />self.postMessage("Inside worker1.js!");<br />2011-08-18<br />18<br />
  19. 19. Worker Sample 2<br />// worker2.html<br />...<br />var data = [1, 2];<br />var worker = new Worker("worker2.js");<br />worker.onmessage = function(event) {<br /> console.log("Received: [" + event.data + "]");<br /> };<br />worker.postMessage(data);<br />...<br />// worker2.js<br />self.onmessage = function(event) {<br />event.data.push(3);<br />self.postMessage(event.data);<br />};<br />2011-08-18<br />19<br />
  20. 20. SharedWorker Sample 1<br />// sharedworker1.html<br />...<br /> function messageHandler(event) {<br /> console.log("Received: [" + event.data + "]");<br /> };<br />var sharedworker1 = new SharedWorker("sharedworker1.js", "b4you");<br />var sharedworker2 = new SharedWorker("sharedworker1.js", "b4you");<br /> sharedworker1.port.onmessage = messageHandler;<br /> sharedworker2.port.onmessage = messageHandler;<br />...<br />// sharedworker1.js<br />var global = 0;<br />self.onconnect = function(event) {<br />event.ports[0].postMessage(global++);<br />};<br />2011-08-18<br />20<br />
  21. 21. SharedWorker Sample 2<br />// sharedworker2.html<br />...<br /> function messageHandler(event) {<br /> console.log("Received: [" + event.data + "]");<br /> };<br />var sharedworker1 = new SharedWorker("sharedworker2.js", "b4you");<br />var sharedworker2 = new SharedWorker("sharedworker2.js", "b4you");<br /> sharedworker1.port.onmessage = messageHandler;<br /> sharedworker2.port.onmessage = messageHandler;<br /> sharedworker1.port.postMessage(1);<br /> sharedworker2.port.postMessage(2);...<br />// sharedworker1.js<br />var global = 0;<br />self.onconnect = function(event) {<br />var port = event.ports[0];<br />port.onmessage = function(event) {<br />port.postMessage(event.data + 1);<br /> }<br />};<br />2011-08-18<br />21<br />
  22. 22. SharedWorker Sample 2<br />2011-08-18<br />22<br />
  23. 23. AJAX in Worker<br />UI Blocking issue<br />AJAX는 비동기 통신이기 때문에 UI가 blocking 되지 않음<br />수신한 데이터를 parsing/filtering 할 때 UI가 blocking 될 수 있음<br />Worker를 사용함으로써 UI blocking 방지<br />2011-08-18<br />23<br />
  24. 24. AJAX in Worker<br />// ajaxworker.html<br />...<br />var worker = new Worker("ajaxworker.js");<br />worker.onmessage = function(event) {<br /> console.log(event.data);<br /> };<br />...<br />// ajaxworker.js<br />varxhr = new XMLHttpRequest();<br />xhr.onreadystatechange = function(){<br /> if ((this.readyState == 4) && (this.status == 200)) {<br />self.postMessage(this);<br /> }<br />};<br />xhr.open("GET", "http://b4you.net/blog/rss", true);<br />xhr.send();<br />2011-08-18<br />24<br />
  25. 25. AJAX in Worker<br />2011-08-18<br />25<br />
  26. 26. Web Workers 성능 향상<br />일반 thread를 사용 하였을 때와 유사<br />Worker만을 사용한다고 해서 성능 향상이 되지 않음<br />성능 향상을 위해 UI/algorithm code를 분리 해서 실행 해야 함<br />시분할 처리 방식을 Worker 방식으로 변환 하였을 때 성능 향상을 기대할 수 있음<br />시분할 처리 방식의 overhead 감소<br />2011-08-18<br />26<br />
  27. 27. Web Workers 성능 향상<br />Web Worker Harness<br />http://ie.microsoft.com/testdrive/HTML5/WebWorkerTest262/Default.html<br />복잡한 수식 연산 benchmark<br />http://www.yafla.com/dforbes/resources/moonbat/moonbat-driver.html<br />2011-08-18<br />27<br />
  28. 28. Web Workers 한계<br />접근 할 수 있는 객체가 제한됨<br />접근 불가 객체 목록<br />window/document object<br />console object(browser object)<br />parent (opener)<br />Worker/SharedWorker<br />2011-08-18<br />28<br />
  29. 29. Web Workers 한계<br />접근 할 수 있는 객체가 제한됨 (cont)<br />접근 가능 객체 목록<br />WorkerNavigator(navigator), WorkerLocation(location)<br />Array, Object, String, Boolean, Date, Error, EvalError, Number, RangeError, ReferenceError, RegExp, SyntaxError, TypeError, URIError, Function, Math<br />XMLHttpRequest, WebSocket, ...<br />2011-08-18<br />29<br />
  30. 30. Web Workers 한계<br />DOM Parsing 불가<br />Worker에서 데이터 가공을 하려면 JSON 형태로 송/수신 해야 함<br />일반 AJAX response<br />Worker 내부에서의 AJAX response<br />2011-08-18<br />30<br />
  31. 31. Web Workers 한계<br />jQuery/prototype.jslibrary사용 불가<br />일부 기능을 제거한 버전을 사용해야 함<br />jQuery.hive()<br />Worker에 대한 abstract layer 제공<br />$.each, $.ajax등 일부 기능을 jQuery와 유사하게 사용 할 수 있음<br />https://github.com/rwldrn/jquery-hive<br />2011-08-18<br />31<br />
  32. 32. $.Hive Sample 1<br />// hive1.html<br />...<br /> $.Hive.create({<br /> worker: 'hive1.js',<br /> receive: function (message) {<br /> console.log(message);<br /> }<br /> });<br /> $.Hive.get(0).send({msg: "hello"});<br />...<br />// hive1.js<br />importScripts('jquery.hive.pollen.js');<br />// $()은 onmessage=와 동일<br />$(function (data) {<br /> $.send(data);<br />});<br />// 또는 다음의 코드를 이용할 수도 있음<br />/*<br />Pollen(function (data) {<br />Pollen.send(data);<br />});<br />*/<br />2011-08-18<br />32<br />
  33. 33. $.Hive Sample 2<br />// hive2.html<br />...<br /> $.Hive.create({<br /> worker: 'hive2.js',<br /> receive: function (message) {<br /> console.log(message);<br /> }<br /> });<br />...<br />// hive2.js<br />importScripts('jquery.hive.pollen.js');<br />// AJAX 요청<br />$.ajax.get({<br />url: "http://b4you.net/blog/rss",<br />dataType: "xml",<br /> success: function(response) {<br /> $.send(response);<br /> }<br />});<br />$.each([1, 2, 3], function(index, item) {<br /> $.send("each test: " + index);<br />});<br />2011-08-18<br />33<br />
  34. 34. 참고 자료<br />jQuery-hive 설명<br />http://bocoup.com/jquery-hive/<br />Using the console object for Worker<br />https://github.com/davidflanagan/WorkerConsole<br />JavaScript Web Workers Local Chrome : Enable via Flag / Parameter<br />http://suretalent.blogspot.com/2011/04/javascript-web-workers-local-chrome.html<br />2011-08-18<br />34<br />
  35. 35. 감사합니다!<br />2011-08-18<br />35<br />

×