JavaScript (ECMAScript) 2013
Upcoming SlideShare
Loading in...5
×

Like this? Share it with your network

Share

JavaScript (ECMAScript) 2013

  • 13,394 views
Uploaded on

HTML5 Conference 2013 で使用したスライド (2013/12/11 Updated) ...

HTML5 Conference 2013 で使用したスライド (2013/12/11 Updated)
http://events.html5j.org/conference/2013/11/

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
13,394
On Slideshare
9,818
From Embeds
3,576
Number of Embeds
23

Actions

Shares
Downloads
81
Comments
0
Likes
44

Embeds 3,576

http://html5experts.jp 2,561
http://stocker.jp 318
https://twitter.com 214
http://feedly.com 189
http://kyotar.com 116
http://www.feedspot.com 63
http://syossan.hateblo.jp 45
http://www.newsblur.com 28
http://eventifier.com 11
http://digg.com 9
http://eventifier.co 6
http://www.eventifier.com 2
http://tweetedtimes.com 2
http://newsblur.com 2
http://r.awks.jp 2
http://www.eventifier.co 1
http://www12243uf.sakura.ne.jp 1
https://www.commafeed.com 1
https://reader.aol.co.jp 1
http://reader.aol.com 1
http://eventifier.info 1
https://www.chatwork.com 1
http://www.google.co.jp 1

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Draft Ecma/TC39/2013/0xx ECMA-262 6th Edition / Draft November 8, 2013 Draft ECMAScript Language Specification JavaScript 2013 Report Errors and Issues at: https://bugs.ecmascript.org Product: Draft for 6th Edition Component: choose an appropriate one Version: Rev 21, November 8, 2013 Draft ECMAScript 6th & JavaScript Fast Parts @HTML5 Conference 2013 by Tomoya Asai (dynamis) Reference number ECMA-123:2009 © Ecma International 2009 Last Update: 2013/12/11
  • 2. about:me
  • 3. Tomoya ASAI Mozilla Japan Technical Marketing (Evangelist) dynamis @ community dynamis.jp @dynamitter facebook.com/dynamis mailto: Tomoya ASAI <dynamis@mozilla-japan.org>
  • 4. Topics
  • 5. 今日のトピック ステキな新機能 Syntax Sugar Class & Module Readable Code 高速化の行方 Slow Parts & Fast Parts asm.js Faster JavaScript
  • 6. 今日扱わないトピック ECMAScript 6 に至る歴史 いろいろ泣ける話があった… 過去の講演スライド参照してね ECMAScript 5.1 までの機能 IE とか Safari が最近対応したば かりとか未実装あるけど割愛 過去の講演スライド参照してね
  • 7. 今日扱わないトピック 説明しても楽しくない機能 API Improvement Internationalization / Globalization 未合意の機能 (strawman) Pallarelism ECMAScript 7th の機能 PromiseResolver
  • 8. See Also...
  • 9. JavaScript.Next Returns 2012 年時点の次世代 JS 解説 JavaScript の歴史も紹介 ECMAScript 5 も一部解説 ES5 も知らない人は先にこちらを 見てからの方が良いかも http://www.slideshare.net/dynamis/javascriptnext-returns
  • 10. Firefox 開発ツール 標準開発ツールの紹介 一昔前とは全然違う Firebug ユーザもご一読あれ 上手く使い分けてね スクラッチパッドもオススメ このスライドでは紹介してないけ どコードサンプルのテストに最適 http://www.slideshare.net/chikoski/firefox-28137532
  • 11. ECMAScript 6th & Harmony
  • 12. JavaScript の課題 仕様上高速化が困難 モジュール性の不足 プロトタイプベースの特殊性 不可思議な this の挙動 Array じゃない Array like 達 非同期処理コールバック地獄 実行時エラーが多い
  • 13. JavaScript 改良への動き 2008 ECMAScript 4th 終了 Yahoo! & MS の反対で挫折 ECMAScript Harmony へ 次世代 ECMAScript コードネーム 2009.12 ECMAScript 5th 小さな変更だけの ES3.1 ベース 2013? ECMAScript 6th 遂に抜本的な改定の時が来た! ECMAScript の標準化は TC39 の 2 ヶ月に1度のミーティングと ML で議論
  • 14. ECMAScript 6th の目標 より開発しやすい言語 想定用途: 複雑なアプリ、ライブラ リ、機械生成コードの実行環境 テスト可能な仕様 相互運用性を確保 バージョニングは単純に 静的検証も可能に 実行よりコンパイル時にエラー検出 http://wiki.ecmascript.org/doku.php?id=harmony:harmony
  • 15. 破棄・断念された提案 typeof null 最初の誤りを訂正したかった… 非互換性が大きすぎる Proxies Direct Proxies に移行 Pragma モードはなるべく少なく
  • 16. Can I Use?
  • 17. ところどころウソもあるけど まぁだいたいこんな対応状況 http://kangax.github.io/es5-compat-table/es6/
  • 18. 実装・対応状況 SpiderMonkey がリード V8 がそれに続く JavaScriptCore や IE は限定的 先行するところも一応ある Traceur は結構対応してる TypeScript は限定的な対応だが JavaScript に変換したコードが 綺麗なのがステキ
  • 19. ECMAScript 5th にコンパイル Traceur Compiler ES Harmony からのコンパイル用 https://github.com/google/traceurcompiler TypeScript ES Harmony の一部+独自拡張 http://typescriptlang.org/ たまに紹介されてる Harmonizr や Six は開発終了したっぽい
  • 20. 特定機能向けコンパイル defs.js let, const だけ変換 https://github.com/olov/defs es6-module-loader Module の import/export を処理 https://github.com/ModuleLoader/es6module-loader その他色々…
  • 21. Shim (Polyfill) で拡張 新しい API や型の一部はプロ トタイプ拡張で対応できる この方式では構文変化は対応不可 es6-shim https://github.com/paulmillr/es6-shim ECMAScript-6 https://github.com/monolithed/ ECMAScript-6
  • 22. Syntax Sugar
  • 23. 分割代入 (Destructuring) 代入左辺を配列やオブジェク トのように書ける記法 Firefox に続けて Safari が対応
 但し仕様準拠はまだ不完全 複数の値のやり取りに便利 一行で済むし見やすくなる 一部の値だけ欲しいとき便利 特に JSON データ処理など http://wiki.ecmascript.org/doku.php?id=harmony:destructuring
  • 24. 分割代入 (Destructuring) // 配列で受け取るサンプル: // 値の入れ替え [a, b] = [b, a]; ! // 関数から複数の値を返して一気に変数に代入 var [c,d] = (function f() { return [1,2]; })(); // -> c=1, d=2 ! // 一部省略や入れ子も可能 var [e,,[x,y]] = (function f(){
 return [3,4,[10,20]] })(); // -> e=3,x=10,y=20 http://wiki.ecmascript.org/doku.php?id=harmony:destructuring
  • 25. 分割代入 (Destructuring) // オブジェクトで受け取るサンプル var fx={ name:"Firefox", vendor:"Mozilla", ver:26 }; var ch={ name:"Chrome", vendor:"Google", ver:31 }; var browsers={ firefox: fx, chrome: ch }; ! // 欲しいプロパティだけ一括代入 var { name: n, ver: v } = fx; // -> n="Firefox", v=26 ! // 関数の引数から必要なプロパティだけ受け取る (function ({ vendor: ven }) { console.log(ven); })(fx); // -> "Mozilla" http://wiki.ecmascript.org/doku.php?id=harmony:destructuring
  • 26. 未実装や議論中の構文例 // 最終的にどうなるか分かってません m(_ _)m ! // default value let { foo = 10, bar = 5 } = { foo: 12 }; console.log(foo); // 12 console.log(bar); // 5 ! // 関数の引数での rest element function foo([x, ...xs]) {} http://wiki.ecmascript.org/doku.php?id=harmony:destructuring
  • 27. default & rest parameter モダンな言語では当然の機能 だが Firefox 以外は未サポート default parameter 引数のデフォルト値を設定 rest parameter 残りの引数を配列で受け取る
  • 28. default parameter e = document.body; // 何か適当な要素 function setBackgroundColor(element, color='orange') { element.style.backgroundColor = color; } setBackgroundColor(e); // オレンジに setBackgroundColor(e, 'blue'); // 青に setBackgroundColor(e, undefined); // オレンジに ! // デフォルト値は呼び出し毎に生成される // 同一オブジェクトが渡される Python などとは違う function getObject(o={}) { return o; } getObject() == getObject() // -> false http://wiki.ecmascript.org/doku.php?id=harmony:parameter_default_values
  • 29. rest parameter function f(a, b, ...args) { return args; } f("IE", "Chrome"); // -> [] f("IE", "Chrome", "Firefox"); // -> ["Firefox"] ! // rest arguments は Array のメソッドが使える // [].slice.call(arguments) ハックとか不要に function sortRestArgs(...args) {   var sortedArgs = args.sort();   return sortedArgs; } http://wiki.ecmascript.org/doku.php?id=harmony:rest_parameters
  • 30. ! 配列の内包表記 (Comprehensions) 配列の内包表記 Python や Haskell にもあるやつ 最近構文変わったので注意! Firefox 2 12 は JS1.7 の構文 Firefox 13 は旧 ES6 仕様 2013.01 に変更された (RTL→LTR) 最新 ES6 構文の実装はまだない http://wiki.ecmascript.org/doku.php?id=harmony:array_comprehensions
  • 31. 配列の内包表記 (Comprehensions) // 配列のフィルタとマップ [for (x of [1,-4,5,3,-7]) if (x > 0) x] // -> [1, 5, 3] // ES5 なら次のように書く // [1,-4,5,3,-7].filter(function(x) { return x > 0 }); [for (x of [2,4,6]) x*x] // -> [4, 16, 36] // ES5 なら次のように書く: // [2,4,6].map(function (x) { return x*xi }); ! // 配列のデカルト積やラベル生成もシンプルに [for (i of [0,2,4]) for (j of [5,3]) i*j] // -> [0, 0, 10, 6, 20, 12] [for (x of 'abc'.split('')) for (y of '123'.split('')) (x+y)]; // -> ["a1","a2","a3","b1","b2","b3","c1","c2","c3"]
  • 32. 配列の内包表記の構文変更 // 旧 ES6 構文 (現行 Firefox の実装) // 値の定義が最初 (for や if の左) return [a+b for (a of A) for (b of B) if (a > b)] ! // 新 ES6 構文 // 値の定義は最後 (for や if の右) return [for (a of A) for (b of B) if (a > b) a+b] ! // 新構文の方が読みやすいので構文変更された https://gist.github.com/dherman/b250d1fad15dbb5f77a5
  • 33. Modularity
  • 34. ブロックスコープ (let, const) ブロックスコープ変数と定数 IE11 でもサポート! Safari は const でも変数になる const は仕様では let 同様ブロッ クスコープの定数だが現在の実装 は var 同様のブロックスコープ
  • 35. let { // let 定義: ブロックスコープ let a = 1, b = 10; // let 式・文: let (...) に続く式・文中だけで有効 let (a = 100, c = 300) console.log(a); // -> 100 // for 文などでの let for (let a=0; a<3; a++) { console.log(a+b); // -> 10, 11, 12 } console.log(a); // -> 1 } console.log(a); // × ReferenceError: a is not // defined
  • 36. const // 不変定数を定義 const browser = "Firefox"; ! // 再定義は TypeError となる const browser = "Internet Explorer"; // TypeError: redeclaration of const browser ! // 定数への代入は単に無視される browser = "Chrome"; console.log(browser); // -> "Firefox"
  • 37. Class 待望の Class です プロトタイプベース OOP の記法に 馴染めない貴方もこれで安心
  • 38. Class の利用例 // クラスベース OOP でよく見る感じ class Animal { constructor(name) { this.name = name; this.hungry = true; } eat() { this.hungry = false; } run() { this.hungry = trye; } }
  • 39. Class - extends // 派生クラスの定義がシンプル class LesserPanda extends Animal { constructor(name, tail) { super(name); this.tail = tail; } }
  • 40. 参考: EcmaScript 5th の場合 // プロトタイプベース function Animal(name) { this.name = name; this.hungry = true; } Animal.prototype.eat = function() { this.hungry = false; } Animal.prototype.run = function() { this.hungry = true; }
  • 41. 参考: ECMAScript 5th で派生 // プロトタイプベースでの派生は少し気持ち悪い function LesserPanda(name, tail) { Animal.call(this, name); this.tail = tail; } LesserPanda.prototype = Object.create(Animal.prototype); LesserPanda.prototype.constructor = LesserPanda;
  • 42. Module ライブラリの import/export 遂に標準機能に! まだブラウザでは未実装なので es6-module-loader などの変換 ツールで処理するしかない… http://wiki.ecmascript.org/doku.php?id=harmony:modules
  • 43. Module module 'math' { export function sum(x, y) { return x + y; } export var hbar = 1.054571726e-34; // ディラック定数 } import {sum, hbar} from 'math'; alert("2 = " + sum(hbar, hbar)); // オブジェクトのプロパティに読み込み module Math from 'math'; alert("2 = " + Math.sum(Math.hbar, Math.hbar));
  • 44. module import いろいろ // module のデフォルト export を読み込み import $ from "jquery"; // 変数のプロパティに読み込み module crypto from "crypto"; // 変数に読み込み import { encrypt, decrypt } from "crypto"; // 別名で読み込み import { encrypt as enc } from "crypto"; // 他のモジュールを読み込んで再 export export * from "crypto"; // 他のモジュールから一部だけ再 export export { foo, bar } from "crypto"; http://wiki.ecmascript.org/doku.php?id=harmony:modules
  • 45. Readable Code
  • 46. Arrow Function コールバックに便利な関数 シンプルに書ける 矢印なんか格好いい 内外で this が固定される Firefox 22 実装 http://d.hatena.ne.jp/teramako/20130321/p1
  • 47. Arrow Function // return するだけのコールバックがシンプルに [1,2,3].map(x => x * x); // ES5 ではこう書く必要があった: // [1,2,3].map(function (x) { return x * x; }); ! // 引数が 1 つ以外の場合は引数を () で括る setInterval(() => { alert("HEY! 提督ぅー!alertしてもイイけどサー、時間 と場所をわきまえなヨー!"); }, Math.random()*10*1000); ! // n! (nの階乗) を求める関数もシンプルに var factorial=((f=n=>n>1 ?n*f(n-1):1)=>(f))(); factorial(10); // 3628800 http://wiki.ecmascript.org/doku.php?id=harmony:arrow_function_syntax
  • 48. Arrow Function における this // this は矢印関数を囲むスコープのものにバインド // コールバック利用時に self=this とか不要になる function Person(){ this.age = 0; setInterval(() => { this.age++; // this は Person オブジェクト }, 1000); } var p = new Person(); ! // 注: strict mode でも this はレキシカルに bind // 済みとして振る舞うので undefined にならない https://developer.mozilla.org/docs/Web/JavaScript/Reference/arrow_functions
  • 49. Generator Python のジェネレータから Firefox が最初に実装 現行仕様とは構文が異なる 最近 V8 が一部実装 最新仕様で動きます http://wiki.ecmascript.org/doku.php?id=harmony:generators
  • 50. Generator 用語 イテレータ (iterator) {value, done} を返す next メソッドを 持つオブジェクト ジェネレータ (generator) ジェネレータ関数で挙動を定義・生 成されているイテレータ ジェネレータ関数 ジェネレータを生成する特殊な関数 yield で next で返す value を指定 http://domenic.me/2013/09/06/es6-iterators-generators-and-iterables/
  • 51. Generator を使ったループ処理 // ジェネレータ関数 (ジェネレータのコンストラクタ) function* fibonacci() { let [prev, curr] = [0, 1]; for (;;) { [prev, curr] = [curr, prev + curr]; yield curr; // 値を返して一時停止 } } for (n of fibonacci()) { if (n > 20) break; console.log(n); // 順に 1, 2, 3, 5, 8, 13 }
  • 52. Iterator としての Generator function* counterGenerator() { let c = 0; for (;;) { yield c++; // 値を返して一時停止 } } // ジェネレータを生成 let counter = counterGenerator(); // next() メソッドで {value, done} を得る counter.next(); // -> {value: 0, done: false} counter.next(); // -> {value: 2, done: false} counter.next().value; // -> 2 counter.next().value; // -> 3 補足: Generator を複数生成したらそれぞれ独立してカウントできます
  • 53. Promise 非同期処理を綺麗に さらばコールバック地獄 deferred よりも綺麗 Firefox や V8 で実装 今日の基調講演で及川さんも紹介 していましたよね!
  • 54. Promise で非同期処理 let p = new Promise(function (resolve, reject) { // 3 秒後に resolve 呼んでプロミスが解決する setTimeout(resolve, 3000); }); ! // 解決した (resolve が呼ばれた) ときに実行: p.then(function () { alert('3 秒たったよ!'); }).then(function () { // 解決済みなので即ここも実行される alert('既に 3 秒過ぎてるよ!'); }); 詳しい日本語解説: http://js-next.hatenablog.com/entry/2013/11/28/093230
  • 55. Promise で引数を使う let p = new Promise(function (resolve, reject) { // 60 秒後にこのプロミスは解決する // resolve の引数に "60 秒!" を渡す setTimeout(resolve, 60*1000, "60 秒!"); }); ! // resolve の引数を受け取って使う p.then(function (message) { alert(message); // -> "60 秒!" と表示される })
  • 56. Promise でエラーハンドリング p = new Promise(function (resolve, reject) { dream(); // 未定義の関数を呼ぶ (エラー発生) }) ! // エラー発生時は then をスキップして catch へ p.then(function (message) { // p は解決しないのでこのブロックは実行されない alert(message); }).catch(function (error) { // p でエラーが発生するのでこのブロックを実行 alert(error); // -> ReferenceError: dream is not defined });
  • 57. Promise のチェイン // s 秒後に解決して resolve に s を渡す Promise を作って返す関数 function wait(s) { var p = new Promise(function (resolve) { setTimeout(resolve, s*1000, s) }); return p; // Promise を返す } // ログを吐いてから s を返す function log(s) { console.log("さっきから "+s+" 秒過ぎたよ") return s; // then で呼ばれたときは Promise にキャストされる } // wait 呼ぶ度に未解決の新しい Promise ができる // 5 秒ごとに 3 回 log が呼ばれる wait(5).then(log).then(wait) .then(log).then(wait) .then(log);
  • 58. XHR に Promise を使う function ajax(url) { return new Promise(function (resolve, reject) { var xhr = new XMLHttpRequest xhr.open('GET', url) xhr.onload = function () { if (xhr.status == 200) { resolve(xhr.response); // 成功時に解決 } else { reject(new Error(xhr.statusText)); // 404 などでリジェクト } } xhr.onerror = reject; // その他のエラー xhr.send(); }) } function onsuccess(response) { alert("成功: "+response); } function onerror(error) { alert("エラー: "+error); } ajax(url).then(onsuccess).catch(onerror) http://js-next.hatenablog.com/entry/2013/11/28/093230
  • 59. New Type & API
  • 60. Collections Simple Set & Map Python: set, dict
 Ruby: Set, Hash
 Java: java.util.HashSet,
 java.util.HashMap
 C++: std::unordered_set
 std::unordered_map WeakMap & WeakSet 弱参照バージョン (割愛)
  • 61. Simple Set var set = new Set(); // 集合に追加・確認・削除 set.add("Firefox"); set.add("Thunderbird"); set.add(+0); set.add(NaN); set.has("Firefox"); // -> true set.has("Sunbird"); // -> false set.delete("Firefox"); set.has("Firefox"); // -> false // -0 と +0 は区別される, NaN は区別されない set.has(-0);  // -> false   set.has(NaN);  // -> true JavaScript は内部的には -0 と +0 が異なるからです
  • 62. Simple Map var map = new Map();   var str = "Mozilla", obj = {}, func = function(){}; // Map に値を格納 map.set(str, "Firefox");   map.set(obj, "Thunderbird");   map.set(func, "Japan");   // キーに対応する値を取得 map.get(str);  // -> "Firefox" map.get(obj);  // -> "Thunderbird" map.get(func); // -> "Japan" // 設定したキーと引数の比較は == ではないので注意 map.get("Mozilla");  // -> "Firefox" map.get({});         // -> undefined map.get(function(){}) // -> undefined キーと引数の比較は === 演算子に近いが厳密には === とも異なる
  • 63. API Improvement (割愛) String の拡張 startsWith, endsWith, contains, repeat, fromCodePoint ... Number の拡張 isFinite, isNaN, isInteger... Math の拡張 cosh, sinh, tanh, arosh, asinh, atanh, log1p, log2, log10, sign ...
  • 64. Slow Parts & Fast Parts
  • 65. Note: JavaScript Good Parts 人間が誤認しにくいコード 意図せぬ挙動を防げる記法 (コー ディング規約) を論理的に解説 Douglas Crockford 提唱 JSON の生みの親、JS 業界の重鎮 ECMAScript 4th を葬った人です 職業: The Boss of You
  • 66. JavaScript が遅い原因 インタープリタ実行 JIT が有効にならないと超遅い 動的型付け言語 型推論が働かないとかなり遅い クラスと配列が存在しない Array は Object の派生 数値の型が Number しかない 2009 年にも書いた: http://www.slideshare.net/dynamis/trace-monkey
  • 67. JavaScript Slow Parts 変数の型を変更 型推論による最適化ができない 遅い原因を克服するエンジンの努 力を無に帰すコードの書き方です プロトタイプチェイン グローバル変数遅い Shape 変わると遅い エンジンが最適化に苦労するコードの書き方 "Slow Parts" もあれば
  • 68. JavaScript Fast Parts 高速処理可能なコード 変数型やオブジェクトの Shape が 一定 (型推論で固定型演算可能) 遅い原因を克服して最適化可能に なっているコードパターンがある 高速処理可能な機能 Typed Array エンジンが最適化できる書き方や高速化のための機能 ”Fast Parts" もある
  • 69. Typed Array 型固定配列で高速数値演算 元々 WebGL で導入され FileAPI, XHR2, WebSocket などでも採用 分離して ECMA6th にも入った IE9 非サポートに注意 shim はいろいろある https://github.com/jDataView/jDataView https://bitbucket.org/lindenlab/llsd/src/ default/js/typedarray.js http://www.khronos.org/registry/typedarray/specs/latest/
  • 70. ArrayBuffer & View ArrayBuffer(byteLength) メモリを確保するバッファ The Typed Array View Types: ArrayBuffer 読み出し用ビュー Int8Array, Unit8Array,
 Int16Array, Uint16Array,
 Int32Array, Uinit32Array,
 Float32Array, Float64Array
  • 71. Typed Array // 16 バイト長のバッファを確保 var buffer = new ArrayBuffer(16); // 32bit 整数 x 4 として読み出すビューを定義 var int32View = new Int32Array(buffer); // 32bit 整数として 0, 2, 4, 6 を格納 for (var i=0; i<int32View.length; i+ +) { int32View[i]=i*2; } // 16bit 整数 x 8 として同じバッファを読み出すビュー var int16View = new Int16Array(buffer); // 実際に読み出してみる for (var i=0; i<int16View.length; i++) {     console.log(int16View[i]);   }   // -> 0, 0, 2, 0, 4, 0, 6, 0 https://developer.mozilla.org/docs/Web/JavaScript/Typed_arrays
  • 72. asm.js
  • 73. asm.js とは JavaScript のサブセット仕様 既存 JavaScript エンジンで動作 高度に最適化可能なパターン 静的型で事前コンパイル可能 経験的に JIT する必要が無い形式 全体または関数単位で有効化 "use asm" とファイルまたは関数 の冒頭に記載する "Fast Parts" (の更に一部) を明文化・定義したもの http://asmjs.org/
  • 74. asm.js の設計思想 演算結果を固定型に 型の明示 (Annotation) も既存 JavaScript の範囲内で行う TypedArray でメモリ管理 ガーベジコレクションを回避 機械生成が前提の設計 C 言語などから変換する対象 C 言語に追いつくための設計 http://asmjs.org/
  • 75. asm.js がもたらすもの Web を Native の速度に CrankShaft や IonMonkey の SSA 最 適化 JIT の効果を確実かつオーバー ヘッドなく使えるように 予測可能なパフォーマンス 暗黙知 (ダーティハック) にお別れ ams.js 形式で書けば必ず十分に高 速化されることが保証される 予測不能な JIT/GC を回避 "Fast Parts" である ams.js なら確実に速く http://asmjs.org/
  • 76. 大規模アプリは遅かった 大規模アプリの処理速度では C 言語が圧倒的に速い (小規模アプリや一部ベンチ限定で以前から高速) 2013/03 - http://kripken.github.io/mloc_emscripten_talk/#/19
  • 77. C 言語に迫る高速化 (asm.js) asm.js 導入直後で既に C の 2 倍遅い程度まで (Java や C# の処理速度と同程度以上の水準に) 2013/03 - http://kripken.github.io/mloc_emscripten_talk/#/19
  • 78. C 言語に迫る高速化 (asm.js) asm.js 形式の JavaScript コード実行速度は C 言語より数割遅い程度まで迫りまだ高速化中 2013/09 - http://kripken.github.io/mloc_emscripten_talk/sloop.html#/7
  • 79. 実レベル: Box2D 物理演算エンジン Box2D では C 言語の 2 倍遅い程度の速度 ! Chrome や IE でも通常の JS より asm.js が高速 Box2DWeb のコードが悪いって話を差し引いても十分 ! Java や CrossBridge (Flash C++ Compiler) と同等以上 2013/07 - http://kripken.github.io/mloc_emscripten_talk/sloop.html#/8
  • 80. 実用例: Unreal Engine 3 100 万行以上の C & OpenGL コードを 4 5 日で移植 LLVM + Emscripten で JavaScript (asm.js) に変換 epic CITADEL http://www.unrealengine.com/html5/
  • 81. 日経コミュニケーション 201306 への寄稿原稿から引用
  • 82. asm.js にまつわる誤解 機械生成なんてナンセンス !? CoffeeScript や TypeScript どころ か 2006 年には GWT 出てる 特定パターンだけ高速は反則 ベンチを中心に特定パターンへの 最適化が積み重ねられてます Emscripten などの機械生成コード 利用も広がっておりいずれにして も最適化対象となるパターン http://mozakai.blogspot.jp/2013/06/what-asmjs-is-and-what-asmjs-isnt.html
  • 83. asm.js にまつわる誤解 x = x¦0 とか非対応だと重い !? 既存エンジンが既に最適化していた パターン (SunSpider crypto 等) 高速実行可能なコード生成を行っ ていたツールからできた規則 特殊な JIT エンジンが必要 既存エンジンの簡単な拡張 Firefox では 3 人月、Chrome も 数ヶ月で最適化対応を進めた http://mozakai.blogspot.jp/2013/06/what-asmjs-is-and-what-asmjs-isnt.html
  • 84. asm.js にまつわる誤解 asm.js は新しい技術 !? 高速コード生成対象パターン 既存の最適化 JIT (CrankShaft や IonMonkey) でコンパイルされる asm.js は新しい仕様 JavaScript のサブセット
 固定型は TypedArray で定義済み Emscripten 実行速度は Mozilla だけ 有利とならず透明性を高めるため http://mozakai.blogspot.jp/2013/06/what-asmjs-is-and-what-asmjs-isnt.html
  • 85. asm.js にまつわる誤解 "use asm" での AOT は反則 !? 型の変わらないコードに対しては元々 原理的には AOT 可能 (だが大変) 機械生成で AOT 可能と保証できる なら経験則で判別する必要ない ES6 の Math.imul に依存してる 32bit 整数演算を行う関数 (後述) 影響は限定的だし Polyfill あります asm.js 専用で生まれた訳じゃない http://mozakai.blogspot.jp/2013/06/what-asmjs-is-and-what-asmjs-isnt.html
  • 86. asm.js にまつわる誤解 PNaCl との一騎打ち !? C++ で書いたコードを高速に Web で動かすという目的は一緒 HTML5 同様に既存 JS との互換性 を重視したアプローチが asm.js PNaCl の成否に依らず JS の一部 である asm.js への最適化は続く http://mozakai.blogspot.jp/2013/06/what-asmjs-is-and-what-asmjs-isnt.html
  • 87. 参考: C to JS コンパイラ比較 Emscripten Mandreel Duetto ライセンス OSS プロプラ 一部プロプラ アーキテクチャ LLVM IR LLVM tblgen LLVM IR メモリモデル TypedArray TypedArray JS Object C/C++ 互換性 フル フル 部分的 TypedArray
 JS ネイティブ 関数呼び出し JS ネイティブ をスタックに API その他 C (SDL etc) Mozilla 製 カスタム HTML5 ベース JS 以外にも
 Server-Clients 変換可能 http://mozakai.blogspot.co.uk/2013/11/c-to-javascript-emscripten-mandreel-and.html
  • 88. Faster JavaScript
  • 89. asm.js がまだ C より遅い理由 コンパイルタイム 避けられないオーバーヘッド 別スレッドで AOT したりキャッ シュしたりして解決していく 単精度演算ができない 元々 JavaScript は倍精度のみ SIMD 命令が使えない 4 データ同時処理で 300% 高速化
  • 90. Math.fround 引数を単精度に丸める 単精度演算の明示に利用 明示なしでもエンジンが判断す る・できる場合もあるが限定的 SM, JSC, v8 で実装済み https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Math/fround
  • 91. Math.fround で単精度演算 // 精度によって結果は異なる (1024+0.0001)+1024 // 単精度では 2048 ! // 単精度演算と結果が異なる可能性があるので // 一旦倍精度に変換・演算してから単精度に変換 var f32 = new Float32Array(1000); for (var i = 0; i < 1000; ++i) f32[i] = (f32[i] + f32[i+1]) + 1; ! // Math.fround で明示されれば単精度で実行 var f32 = new Float32Array(1000); for (var i = 0; i < 1000; ++i) f32[i] = Math.fround(f32[i] + f32[i+1]) + 1; https://blog.mozilla.org/javascript/2013/11/07/efficient-float32-arithmetic-in-
  • 92. 単精度演算命令が無いと遅い 倍精度の方が重い CPU あり float32/float64 の相互変換 float32 を倍精度演算するには変換 オーバーヘッドが発生 倍精度の方がメモリを消費 メモリ関連処理時間に影響 単精度なら可能な最適化も 数値演算によっては最適化可能 例えば x = 1024, y = 0.0001, z = 1024, (x+y)+z の結果は精度によって異なる
  • 93. Math.fround による高速化 Desktop (x86) Nexus 10 Nexus 4 Galaxy S3 60% 45% 30% 15% 0% Matrix Inversions Matrix Graphics Exponential Fast Fourier Transfrom Math.fround の導入によって数値演算
 ライブラリの速度が最大 60% 高速化 https://blog.mozilla.org/javascript/2013/11/07/efficient-float32-arithmetic-in-javascript/
  • 94. Math.imul C 同様の 32bit 整数の掛け算 これも高速化を助ける関数 これを使わないとエンジンで常に 最適化できるとは限らない https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Math/imul
  • 95. SIMD Module 128bit SIMD モジュール TypedArray の拡張 対応データ型 float32x4, uint32x4 配列とビュー Float32x4Array, Int32x4Array 既存 TypedArray のビューにも Intel, Google, Mozilla が積極的に取り組んでいるところ
  • 96. SIMD 命令が存在しないと遅い 複数データの並列同時計算 CPU 1 クロックで複数データ処理 同時に扱える数倍だけ速くなる IA32/X64 の MMX/SSE など ARMv7 の NEON など CPU フル活用したいよね! http://wiki.ecmascript.org/doku.php?id=strawman:simd_number
  • 97. SIMD 命令の導入 // 4 つの数値を格納する TypedArray を宣言 var a = float32x4(1.0, 2.0, 3.0, 4.0); var b = float32x4(5.0, 6.0, 7.0, 8.0); ! // 型毎に決まった SIMD 命令で計算実行 var c = SIMD.float32x4.add(a,b); // -> [6.0, 8.0, 10.0, 12.0] // エンジンが最適化で SIMD 使う形に変換できない // 場合に比べてこの計算は 4 倍 (300%) 高速化 https://github.com/johnmccutchan/ecmascript_simd
  • 98. Conclusion
  • 99. Conclusion ステキな新機能一杯 コード量もバグも少なく 大規模開発にも対応可能に 書いてて楽しい言語に! どんどん高速化が進む JavaScript Fast Parts が増える C 言語に迫る高速化が進行中 JavaScript はこれまで通り不可能と言われた壁を乗り越え続けていく…
  • 100. Always bet on JavaScript!