JSX 速さの秘密 - 高速なJavaScriptを書く方法
Upcoming SlideShare
Loading in...5
×
 

JSX 速さの秘密 - 高速なJavaScriptを書く方法

on

  • 18,565 views

JavaScript で高速なコードを書こうとする際に、はまりがちな罠と、JSX のコンパイラでどのように対処しているのかを紹介

JavaScript で高速なコードを書こうとする際に、はまりがちな罠と、JSX のコンパイラでどのように対処しているのかを紹介

Statistics

Views

Total Views
18,565
Views on SlideShare
14,606
Embed Views
3,959

Actions

Likes
46
Downloads
36
Comments
0

18 Embeds 3,959

http://blog.kazuhooku.com 3736
https://twitter.com 120
http://feedly.com 25
http://news.google.com 22
http://tweetedtimes.com 10
http://digg.com 9
http://plus.url.google.com 7
http://www.feedspot.com 6
http://newsblur.com 5
http://kazuho1.rssing.com 4
http://www.hanrss.com 3
http://4278688165584866733_962c2aff29529b4d39678338ceb2b102103d3608.blogspot.com 3
http://webcache.googleusercontent.com 3
http://www.newsblur.com 2
http://translate.googleusercontent.com 1
http://wiki.onakasuita.org 1
http://reader.aol.com 1
http://www.inoreader.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

JSX 速さの秘密 - 高速なJavaScriptを書く方法 JSX 速さの秘密 - 高速なJavaScriptを書く方法 Presentation Transcript

  • JSX 速さの秘密 〜高速なJavaScriptを書く方法〜 DeNA Co., Ltd. Kazuho Oku 1 Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
  • JSXをご存知ですか?  Javaっぽいプログラミング言語です  JavaScriptにコンパイルされます  JavaScriptよりJSXで書いたほうが高速に動作します JSX 速さの秘密 - 高速なJavaScriptを書く方法 2 Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
  • Q. 高速な JavaScript を書く方法を教えてください JSX 速さの秘密 - 高速なJavaScriptを書く方法 3 Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
  • A. JSX を使いましょう JSX 速さの秘密 - 高速なJavaScriptを書く方法 4 Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
  • … JSX 速さの秘密 - 高速なJavaScriptを書く方法 5 Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
  • これだけでは芸がないので、JSX が行っている様々な JavaScript 最適化技法を紹介します。 JSX 速さの秘密 - 高速なJavaScriptを書く方法 6 Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
  • ※これから説明することは、JSXを使って いれば気にする必要のないことです (自動で最適化されますから) JSX 速さの秘密 - 高速なJavaScriptを書く方法 7 Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
  • 目次  高速なJavaScriptを書くための3原則  更なる高速化のために 〜 JSXの最適化コンパイラの仕 事 JSX 速さの秘密 - 高速なJavaScriptを書く方法 8 Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
  • 高速なJavaScriptを書くための3原則 JSX 速さの秘密 - 高速なJavaScriptを書く方法 9 Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
  • 高速なJavaScriptを書くための3原則  オブジェクトを避ける ⁃ 例: arguments を使わない  Hidden Classを意識したコードを書く ⁃ Inline Cache / 配列の要素の型  組み込み関数が速いとは限らない ⁃ 遅くなることがある • 例: Function#apply, Array#forEach JSX 速さの秘密 - 高速なJavaScriptを書く方法 10 Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
  • オブジェクト生成を最小限に  オブジェクト生成を避ける理由 ⁃ メモリ確保に時間がかかる ⁃ GCの原因になる  オブジェクトが生成されるパターン ⁃ new, {...}, [...] ⁃ arguments の使用 • 使った瞬間にオブジェクトが生成されます  オブジェクトが生成されそうで、されないパターン ⁃ ”abc”.foo() • foo 内での this は string? (ES5以降) JSX 速さの秘密 - 高速なJavaScriptを書く方法 11 Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
  • Unboxing in JSX  オブジェクトへのアクセスを、複数のローカル変数への アクセスに変換する最適化  最適化前: var pt = new Point(x, y); …  最適化後: var pt$x = x; var pt$y = y; …  注意点: ⁃ オブジェクトを return したり他クラスのオブジェ クトのプロパティにセットしている場合は使えない JSX 速さの秘密 - 高速なJavaScriptを書く方法 12 Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
  • プロパティアクセスを最小限に  プロパティアクセス=オブジェクトの要素へのアクセス ⁃ 変数の要素へのアクセスなので、変数へのアクセス より遅い  最適化前: Foo.bar foo.func()  最適化後: Foo$bar // プロパティアクセス → 変数アクセス Foo$func(foo) // メソッド呼出 → 関数呼出 // (呼び出されるメソッドも変換) JSX 速さの秘密 - 高速なJavaScriptを書く方法 13 Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
  • newの呼出を避ける  new Type(...) より { ... } の方が高速 ⁃ Safari で有効な最適化。V8 だと遅くなる  最適化前: var pt = new Point(x, y);  最適化後: var pt = { x: x, y: y };  注意点: ⁃ メソッド呼出や instanceof が不可能になる • メソッド呼出については、全頁のメソッドから関数への 変換を適用 JSX 速さの秘密 - 高速なJavaScriptを書く方法 14 Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
  • argumentsを使わない  遅いJavaScriptの例: Point.prototype.set = function (a1, a2) { if (arguments.length == 1) { this.x = a1.x; this.y = a1.y; } else { this.x = a1; this.y = a2; } };  高速に書くには、Point型を引数にとる setByPoint メ ソッドと、座標の組を引数にとる setByXY メソッドを 別個に用意すべき JSX 速さの秘密 - 高速なJavaScriptを書く方法 15 Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
  • argumentsを使わない – JSXの場合  そもそも arguments がない  関数のオーバーロードが可能 ⁃ コンパイル時に別名になる // コンパイル後の名前: set$Lpoint function set(pt : Point) : void { this.x = pt.x; this.y = pt.y; } // コンパイル後の名前: set$NN function set(x : number, y : number) : void { this.x = x; this.y = y; } JSX 速さの秘密 - 高速なJavaScriptを書く方法 16 Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
  • コンストラクタのオーバーロード  通常の関数は名前を変えることでオーバーロード可能  Q. コンストラクタの場合、どうするか?  A. こんなコードを書く (JSXの内部実装より抜粋) function $__jsx_extend(derivations, base) { var ctor = function () {}; ctor.prototype = base.prototype; var proto = new ctor(); for (var i in derivations) derivations[i].prototype = proto; } function Point1(pt) { this.x = pt.x; this.y = pt.y; } function Point2(x, y) { this.x = x; this.y = y; } // new Point1 しても new Point2 しても同じ型のオブジェクトが生成するおまじない $__jsx_extend([ Point1, Point2 ], Object); JSX 速さの秘密 - 高速なJavaScriptを書く方法 17 Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
  • Hidden Classを意識したコードを書く http://v8-io12.appspot.com/ JSX 速さの秘密 - 高速なJavaScriptを書く方法 18 Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
  • Hidden Classを意識したコードを書く (2)  プロパティのセット順を一意に ⁃ JSXではプロパティ初期化時は条件分岐不可能 • → セット順が一意になる • Java と同様  配列の要素型を一定に ⁃ JSXでは要素型毎に配列型を用意 • number[], string[], Object[], Point[], …  配列の要素をdeleteしない ⁃ JSXでは禁止 • nullを代入することで対処(こちらのほうが高速) JSX 速さの秘密 - 高速なJavaScriptを書く方法 19 Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
  • Hidden Classを意識したコードを書く (3)  未初期化の要素にアクセスしない ⁃ JSXでは未初期化の要素にアクセスするとエラー • 注: デバッグビルドのみ ⁃ リリースビルドではエラーチェック省略  Polymorphicなコードを書かない ⁃ JSXではpolymorphicなコードは書けない • クラスベースの型指定が「必須」な処理系だから • テンプレートを使った場合は、引数の型ごとに個別にコ ード生成 JSX 速さの秘密 - 高速なJavaScriptを書く方法 20 Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
  • 組み込み関数が速いとは限らない  JavaScript VMの仕事 ⁃ JavaScriptを機械語にJust-In-Time compile • 使われるテクニック: ⁃ Inline Caching ⁃ インライン展開  JavaScriptからC++コードを呼ぶのは遅い(逆も同様) ⁃ C++側で様々なチェックが必要 • 引数の数や型の確認等 • 言語をまたいだInline Cachingやインライン展開は無理 ⁃ C++コードは静的にコンパイルされているため JSX 速さの秘密 - 高速なJavaScriptを書く方法 21 Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
  • 組み込み関数が速いとは限らない (2)  汎用的なAPIとして定義されているため遅いケースも ⁃ 数十倍遅いケースも  避けるべき組み込み関数の代表例: ⁃ Function.prototype.call ⁃ Function.prototype.apply ⁃ Function.prototype.bind ⁃ Array.prototype.forEach  ベンチマーク: ⁃ http://jsperf.com/f-p-bind-vs-closure ⁃ http://d.hatena.ne.jp/kazuhooku/20120612/133948 9758 JSX 速さの秘密 - 高速なJavaScriptを書く方法 22 Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
  • 組み込み関数が速いとは限らない (3)  JSXの場合: ⁃ Function.prototype 系は存在しない ⁃ クロージャがthisを引き継げるような言語仕様 • → bindの必要性が低い • JSXのソースコード: var f = function () : void { this.n++; }; • コンパイル結果 (JavaScript): var $this = this; var f = function (){ $this.n++; }; JSX 速さの秘密 - 高速なJavaScriptを書く方法 23 Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
  • 組み込み関数が速いとは限らない (4)  JSXの場合: ⁃ Array#forEachは独自に実装 ⁃ 言語仕様が硬い分、JavaScriptよりも処理が単純に ⁃ 参照: http://d.hatena.ne.jp/kazuhooku/20120612/133948 9758 JSX 速さの秘密 - 高速なJavaScriptを書く方法 24 Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
  • 更なる高速化のために 〜 JSXの最適化コンパイラの仕事 JSX 速さの秘密 - 高速なJavaScriptを書く方法 25 Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
  • インライン展開  JavaScript VMは、インライン展開を行う ⁃ だが、最速ではない • 理由: 毎回、呼び出される関数が差し替えられていない か確認する必要があるため ⁃ JSXの場合: • コンパイル後に関数の差し替え不可能 • 最適化コンパイル時に、あらかじめインライン展開され たJavaScriptを生成 ⁃ → JavaScript VMによるインライン展開より高速 ⁃ → 他の最適化も適用可能に JSX 速さの秘密 - 高速なJavaScriptを書く方法 26 Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
  • 事前計算  定数畳み込み ⁃ JSXのソースコード: const name = ”John”; … console.log(”Hello, ” + N); ⁃ コンパイル結果 (JavaScript): console.log(”Hello, John”); JSX 速さの秘密 - 高速なJavaScriptを書く方法 27 Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
  • 事前計算 (その2)  Dead-code Elimination ⁃ JSXのソースコード: const DEBUG = 0; … if (DEBUG) console.log(”in debug mode”); ⁃ コンパイル結果 (JavaScript): // からっぽ JSX 速さの秘密 - 高速なJavaScriptを書く方法 28 Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
  • LTO (リンク時最適化)  以下のコードで、mの型は何? function transform(m: Matrix, pt : Point) : Point { return m.rotate(pt); }  mの型はMatrix型かもしれないし、Matrixの派生型かも ⁃ これでは、rotateの実装を特定できない • → rotateをインライン展開できない  そこでLTO! ⁃ LTO: プログラムが使用する全てのコードに関する情 報を使って(つまり、リンク時に)最適化 ⁃ Matrixを継承した型がなければ、mの型はMatrix型 JSX 速さの秘密 - 高速なJavaScriptを書く方法 29 Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
  • アフィン変換 (クラス定義) class Matrix { var m11 : number; var m21 : number; var m31 : number; var m12 : number; var m22 : number; var m32 : number; ... function transform(pt : Point): Point { return new Point( this.m11 * pt.x + this.m21 * pt.y + this.m31, this.m12 * pt.x + this.m22 * pt.y + this.m32); } } class Point { var x : number; var y : number; function constructor(x : number, y : number) { this.x = x; this.y = y; } ... JSX 速さの秘密 - 高速なJavaScriptを書く方法 30 Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
  • アフィン変換 (コンパイル例)  JSXのソースコード: var pt = new Matrix(1, 0, 0, 0, 2, 0).transform(new Point(x, y)); x = pt.x; y = pt.y;  最適化コンパイル後 (JavaScript): var pt$x = x + 0 * y; y = 0 * x + 2 * y; x = pt$x;  適用された最適化手法: ⁃ LTO (transformの実装を確定) ⁃ インライン展開 ⁃ Unboxing ⁃ 定数畳み込みとDCE JSX 速さの秘密 - 高速なJavaScriptを書く方法 31 Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
  • まとめ JSX 速さの秘密 - 高速なJavaScriptを書く方法 32 Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
  • 高速なJavaScriptを書ける自信はありますか?  JavaScriptには速度が遅くなる罠が色々 ⁃ 速くできるところが速くなった結果、罠に落ちた時 の速度の落ち込みが大きくなった  モジュールをまたぐ最適化で高速になるケースも ⁃ 例: アフィン変換  高速かつメンテナンスが容易なJavaScriptコードを書く のは難しすぎる ⁃ グループ開発では教育コストが大きくなりすぎる ⁃ 問題が顕在化してから対処するのでは間に合わない JSX 速さの秘密 - 高速なJavaScriptを書く方法 33 Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.
  • JSXを使えば問題解決するよ!!! JSX 速さの秘密 - 高速なJavaScriptを書く方法 34 Copyright (C) 2013 DeNA Co.,Ltd. All Rights Reserved.