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

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Saving this for later?

Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime - even offline.

Text the download link to your phone

Standard text messaging rates apply

JavaScript (ECMAScript) 2013

12,007
views

Published on

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

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

Published in: Technology

0 Comments
44 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
12,007
On Slideshare
0
From Embeds
0
Number of Embeds
29
Actions
Shares
0
Downloads
82
Comments
0
Likes
44
Embeds 0
No embeds

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!