레이블이 javascript인 게시물을 표시합니다. 모든 게시물 표시
레이블이 javascript인 게시물을 표시합니다. 모든 게시물 표시

2018년 1월 23일 화요일

자바스크립트 스터디

A Tale of TurboFan: Four years that changed V8 forever

Inlining

Escape Analysis and Scalar Replacement

Making WebAssembly even faster: Firefox's new streaming and tiering compiler

Streaming compilation : Tier 1(or baseline compiler) and Tier 2 compiler

New bottleneck: CPU - main thread

Caching .wasm file

The Cost Of JavaScript

Bottleneck = Network(transmission size) + CPU(parse time)

JavaScript Startup Bytecode Cache

Optimizing hash tables: hiding the hash code

private symbol을 사용 -> symbol lookup이 필요

Backing store를 사용 -> lookup이 필요없게 되었다. 성능 향상!
: empty, array, dictionary

Fast Properties in V8

Named properties vs Indexed properties

Hidden classes and Descriptor arrays

In-object, fast, slow

Explaining JavaScript VMs in JavaScript - Inline Cached

Must-Watch JavaScript

In The Loop

Tasks - Animation callbacks - Microtasks

Tasks: 한번에 하나만 실행
Animation callbacks: 실행 시점에 큐에 있는 것은 모두 실행(실행 중 추가된 콜백은 다음번에 실행)
Microtasks: 큐가 빌때까지 계속 실행(따라서, 무한히 실행하는 것에 주의 필요)

자바스크립트와 이벤트 루프

Tasks, microtasks, queues and schedules

How JavaScript Timers Work

setTimeout vs setInterval

setInterval : 큐에 이전 핸들러가 실행되지 못하고 남아 있으면 새로 추가하지 않는다.

Elements kinds in V8

small integer -> PACKED_SMI_ELEMENTS
floating-point number -> PACKED_DOUBLE_ELEMENTS
regular element(string) -> PACKED_ELEMENTS

from PACKED to HOLEY

Avoid creating holes
Avoid reading beyond the length of the array
Avoid elements kind transitions
Prefer arrays over array-like objects
Avoid polymorphism

Bubbling and capturing

A cartoon guide to Flux

2016년 11월 8일 화요일

WebTorrent 소스 분석

https://github.com/feross/webtorrent

bittorrent-dht

  • 처음 시작시 find_node로 node들을 찾는다. lookup으로 내가 원하는 info_hash를 가지고 있는 node들을 찾는다. announce로 node들에게 내가 info_hash를 다운받고 있음을 알린다. ping으로 node가 살아있는지 확인한다. 에러가 발생하면 error를 응답한다.
  • 'KRPC Protocol'에 관련된 부분은 k-rpc 모듈에 의해 이루어진다.
  • id는 k-rpc 생성시 만들어진다.
  • _tables: info_hash를 key로 하여 찾은 node 정보를 저장한다.
  • _values: arbitrary payload를 저장한다.
  • _peers: 나에게 announce 쿼리를 보낸 peer 정보를 저장한다.
  • 5분마다 secret 값을 변경한다. secret는 token 생성에 사용된다.
  • routing table에 있는 값들의 저장을 위해 toJSON 함수를 제공한다.
    • toJSON 함수를 사용하여 뽑아낸 node와 value의 정보를 디스크등에 저장해 놓았다가 다시 시작시 addNode를 통해 routing table에 추가할 수 있다.
  • find_node
    • query: { "a": { "id": "<querying nodes id>", "target": "<id of target node>" }
    • 이 작업이 이루어짐으로서 서버로부터 관련 node들의 정보가 routing table에 저장된다.
    • k-rpc에서 기본으로 사용하는 서버들(BOOTSTRAP_NODES)이 있다: router.bittorrent.com:6881, router.utorrent.com:6881, dht.transmissionbt.com:6881
  • lookup
    • query: { "q": "get-peers", "a": { "id": "<querying nodes id>", "info_hash": "<20-byte infohash of target torrent>" } }
    • 응답이 오면 k-bucket에 넣고(id, host, port, token) 'peer' event를 emit한다. peer는 {host, port}이다.
  • announce
    • table에서 info_hash에 연결되어 있는 k-bucket을 찾는다. 여기에는 info_hash를 가지고 있는 node들의 정보가 들어있다. 여기서 info_hash에 closest인 node들을 찾아 이들에 announce를 한다.
    • query: { "q": "announce_peer", "a": { "id": "<querying nodes id>", "token": "<response to a previous get_peers query>", "info_hash": "<20-byte infohash of target torrent>", "port": "port", "implied_port": "0 or 1" } }
  • ping
    • query: { "q": "ping" }
    • response: { "r": "<querying nodes id>" }
  • error
    • response: { "e":[201, "A Generic Error Ocurred"] }

webtorrent

  • handshake를 보낸다. -> (bitfield를 받는다. -> request를 보낸다. -> piece를 받는다.) -> keep-alive를 60s마다 받는다. -> (interested를 받는다. -> unchoked를 보낸다.) -> peer가 DHT를 지원하는 경우 자신의 DHT 포트를 알리는 port를 받는다. -> 모든 piece를 다 받은 경우 본인을 seeder로 설정하고 remote peer에 choked를 보낸다.

BitTorrent Protocol

  • handshake: <pstrlen><pstr><reserved><info_hash><peer_id>
    • 상대 client와 연결시 첫번째로 보내는 메시지.
    • version 1.0의 경우 pstrlen = 19이고 pstr = "BitTorrent protocol" 이다.
  • message format: <length prefix><message ID><payload>
  • port: <len=0003><id=9><listen-port>
    • DHT를 구현하고 있는 경우 remote peer에게 보내는 메시지.
  • keep-alive: <len=0000>
    • 연결이 끊기지 않도록 하기 위해 보내는 메시지. 보통 2분마다 보낸다(webtorrent는 1분마다 보낸다).
  • bitfield: <len=0001+X><id=5><bitfield>
    • 어떤 piece를 가지고 있고 안가지고 있는지를 알리는 메시지.
    • bit에서 cleared는 missing piece를 set은 downloaded를 의미한다.
    • lazy bitfield: 모든 bit를 cleared 하여 받은 부분이 없다고 알린 후, have 메시지로 가지고 있는 부분을 알리는 방법. ISP filtering을 막는 방법이라고 알려져 있다.
  • have: <len=0005><id=4><piece index>
    • 가지고 있는 piece의 index를 알리는 메시지
  • request: <len=0013><id=6><index><begin><length>
    • 지정한 piece를 요청한다.
  • piece: <len=0009+X><id=7><index><begin><block>
    • 요청받은 piece를 응답한다.
  • state information: interested and choked
    • interested는 remote peer가 block을 요청할 것이라는 것을 의미하고 choked는 remote peer가 요청에 응답을 주지 않을 것이라는 것을 의미한다.
    • interested: <len=0001><id=2>
    • not interested: <len=0001><id=3>
    • choke: <len=0001><id=0>
    • unchoke: <len=0001><id=1>

2016년 10월 14일 금요일

Electron Internals 요약

1. http://electron.atom.io/blog/2016/07/28/electron-internals-node-integration

Node와 GUI programming을 같이 사용하는 경우 Node 자체의 event message loop(libuv를 사용한다.)와 GUI 자체의 event loop 두개가 있게 되는 문제가 있다.  main thread는 한 loop에서만 동작해야 하기 때문이다.
이의 해결을 위한 첫 시도는 크로미움의 main process와 renderer process의 message loop를 libuv로 변경하는 것이었다. renderer process의 message loop를 변경하는 것은 간단했으나 main process의 message loop를 변경하는 것은 매우 어려웠다. 각각의 플랫폼마다 다른 message loop를 사용하기 때문에 이를 libuv에 전달해주는 것이 간단하지 않았다. 결국 매우 작은 주기의 timer를 GUI message loop에 추가하는 방법으로 문제를 해결하고자 하였다.
하지만, libuv가 발전하면서 backend fd라는 개념이 도입이 되었고 이것을 polling함으로서 libuv에서의 event에 노티를 받는 것이 가능해졌다. 그래서 backend fd를 polling하여 event가 발생하면 이를 크로미움의 message loop에 전달해주는 별도의 쓰레드를 만드는 것으로 변경하였다. 이 방법을 사용함으로서 크로미움과 노드의 코드를 변경할 필요가 없게 되었다.

2. http://electron.atom.io/blog/2016/08/08/electron-internals-using-node-as-a-library

- Node와 Electron은 빌드 시스템으로 GYP를 사용한다.
- Electron은 node의 빌드를 위해 node의 configure script를 사용하지 않고 자체 빌드 스크립트를 사용한다.
- Electron은 node를 shared library로 사용하고 node의 v8은 사용하지 않는다.
- Electron은 과거에는 node를 static library했다가 지금은 shared library로 빌드한다.
- Node의 native module들은 V8의 심볼이 필요한데 Electron은 node의 V8을 사용하지 않기 때문에 문제가 있다. 그래서 크로미움의 V8의 심볼들은 외부로 expose 하는게 필요하다.
- Electron은 node를 두가지 모드로 시작할 수 있다. standalone mode와 embedded mode

3. http://electron.atom.io/blog/2016/09/20/electron-internals-weak-references

Weak reference는 object가 가비지 콜렉트 되는 것과 상관없이 object를 사용할 수 있도록 해주는 object에의 reference이다.
자바스크립트에서 weak reference와 관련된 것은 WeakMap이다.
Remote module: RPC를 사용하여 render process에서 main process의 object를 사용할 수 있도록 해준다.
-- renderer process에서 object를 요청하면 main process에 메시지를 보낸다.
-- 메시지를 받은 main process는 map에 object를 생성하고 ID를 생성한다. 이 ID를 renderer process에 돌려준다.
-- remote module은 ID를 받으면 이것을 proxy object로 감싼다. renderer process는 이 proxy object를 사용한다. 사용이 끝나면 proxy object가 가비지 콜렉트 될 때 메시지를 main process에 보내 할당된 object도 가비지 콜렉트 될 수 있도록 한다.

같은 object를 여러번 요청하는 경우 메모리 낭비의 문제가 생길 수 있다. - 이의 해결책은?
- Cache: 같은 ID의 object가 이미 있는 경우 새로 생성하지 않고 기존의 object를 리턴한다.
- 이를 위해 WeakMap을 사용한다.

Generic interfaces 요점

 https://go.dev/blog/generic-interfaces  Generic interface를 정의할 때 최소한의 제약만을 정의하고 실제 구현체들이 자신만의 필요한 제약을 추가할 수 있도록 하는 것이 좋다. pointer receiver를...