1. ブラウザ JavaScr ip t 高速化
JIT バトル最終決戦
12-B-5 森田創
Co m m u n it y En g in e, In c
o m o @d o d g so n .o r g
2. 本日の趣旨
J a va S c r ip t VM に使われている
高速化技法を
紹介します。
2
3. 自己紹介
森田創
勤め先 : Co mm unity Eng ine ( 株 )
●
オンラインゲームなどの開発や開発支援
オンラインゲームのミドルウェア販売
仕事 :↑ らのためにコードを書くこと
●
主に C+ + ( たまに r ub y, p ytho n, Ac t io nS c r ip t...)
●
ウェブとかよくわかんない
●
アマチュア J a va S c r ip t VM 評論家
●
↑ これでよばれた。
3
7. /speedup|optimiz/ の回数
@Saf ar i JS エンジンの ChangeLog
50
45
40
35
30
Go o g le Chr o me 登場
25
20
S a f a r i J S 刷新
15
S a f a r i リリース “ x”登場
Aja
10
5
0
02
02
03
03
04
05
05
06
06
07
07
08
/0
/1
/0
/0
/0
/0
/1
/0
/0
/0
/0
/1
6
3
0
7
2
9
4
1
1
8
5
2
/0
/0
/0
/0
/0
/0
/0
/0
/0
/0
/0
/0
7
1
1
1
1
1
1
1
1
1
1
1
1
12. ブラウザ J a v a Sc r ip t 高速化
J IT バトル最終決戦
観戦ガイド
森田創
Co m m u n it y En g in e, In c
o m o @d o d g so n .o r g
12
13. これまでのあらすじ
登場人物 VM x3
V8
●
f r o m Go o g le Chro m e
SquirrelFish Extreme
●
f r o m Ap p le S a f a ri/We b Kit
TraceM onkey
●
f r o m Mo zilla Fire f o x
が、血みどろの戦いを繰り広げていた!!!
13
14. V8 の系譜
S un から引き抜かれた
●
La r s Ba k がエース
S t r o ng ta lk VM
●
J a va Ho t s p o t VM
●
コードにも
●
S t r ong t a lk の残骸
GC
●
アセンブラ
●
14
15. SquirrelFish Extreme の系譜
J a va S c r ip tCo r e 高速化バージョン
●
バイトコード化 (“ q uirr e lFis h”
●
S )
J IT 追加 (“
●
Extre m e ”
)
KHTML/KJ S から派生
●
まだあるよ↑
●
15
16. TraceMonkey の系譜
S p id e rMo nke y
●
+
Ta m a r in Tr a c ing
And r e a s Ga l の研究成果
●
コードも書いてる
●
16
17. 決戦の舞台
V8
●
b r a nc he s /b le e d ing _e d g e r1198
S q uir re lFis h Extre me
●
t r unk r40447
Tr a c e Mo nke y
●
hg .m o zilla .o rg /tr a c e m o nke y 24328
スライド作成時の最新版
※ すべて未リリース
17
18. 本題 :JavaScript VM の高速化
J a va S c r ip t は遅い。なぜなら・・・
昔は実装をさぼっていた。
●
うざいポップアップを出せればよかった。
●
g m a il も zo ho もなかった。
●
言語仕様も割と面倒。
●
でも最近はがんばっている。
●
最終決戦ですから !
●
今日のテーマ
18
19. JSVM 高速化の戦略
J S 言語固有の面倒をとりのぞき、
●
既存 VM の高速化技法をとりいれる
●
J a va , S ma llta lk, Lis p , …
●
ウェブアプリのツボをチューンする
●
19
20. JSVM 高速化の見所3つ
J S 言語固有の面倒をとりのぞき、
●
既存 VM の高速化技法をとりいれる
●
J a va , S ma llta lk, Lis p , …
●
ウェブアプリのツボをチューンする
●
20
21. JSVM 高速化の見所3つ+1
J S 言語固有の面倒をとりのぞき、
●
既存 VM の高速化技法をとりいれる
●
J a va , S ma llta lk, Lis p , …
●
ウェブアプリのツボをチューンする
●
競合 VM への追従
●
オープンソース+宣伝熱心
●
∴ノーガードぱくり殴り合い
21
22. ここからのあらすじ
J S 言語固有の面倒 :
●
クラスがないのをどうにかする話
既存 VM 技術の応用 :
●
メソッド呼び出しの高速化の話
ウェブアプリのツボ :
●
正規表現の高速化の話
どれも三大 VM すべてが実装している
●
激戦区。
22
23. ここからのあらすじ
J S 言語固有の面倒 :
●
クラスがないのをどうにかする話
既存 VM 技術の応用 :
●
メソッド呼び出しの高速化の話ヘ
∴ã€
ウェブアプリ固有のホットスポット :
●
正規表現の高速化の話
23
30. ベンチマーク :
配列 vs. ハッシュ表 in C++
int benchmark(bool use_hash) {
const int NELEM = 100;
if (use_hash) {
std::tr1::unordered_map<int, int> obj;
for (int i=0; i<NELEM; ++i) { obj[i] = i; }
for (int i=0; i<NELEM*NELEM*NELEM; ++i)
{ int x = obj[i%NELEM]; touch(x); }
} else {
int obj[NELEM];
for (int i=0; i<NELEM; ++i) { obj[i] = i; }
for (int i=0; i<NELEM*NELEM*NELEM; ++i)
{ int x = obj[i%NELEM]; touch(x); }
}
}
int touch(int x) { volatile int y = x; }
30
39. 各 VM 上での名前
V8 では
●
Hidden Class
Tr a c e Mo nke y では
●
Shape Inf erence
S q uir re lFis h Extre me では
●
Structure Chain
どれもだいたい同じもの。
●
歴史の長さは TM > V8 > S FX
●
39
48. 復習 (2/3):
JS のメソッド呼び出し
function Greeting() {
this.hello = function() {
alert(quot;hello!quot;);
};
}
var g = new Greeting();
g.hello();
48
49. 復習 (2/3):
JS のメソッド呼び出し
function Greeting() {
this.hello = function() {
alert(quot;hello!quot;);
};
}
/ / プロパティをとりだして
/ / t h is つきで呼ぶのと同じ。
var g = new Greeting();
g.hello(); var gh = g.hello;
gh.apply(g);
49
52. 復習 (3/3) の前に・・・
C++ は静的型付けの言語
変数にクラスがある。
●
int lengthSquared(Point p) {
int x = p.x;
int y = p.y;
int xx = x*x;
int yy = y*y;
int ret = xx + xx;
return ret;
}
52
53. クラスがある=構造がわかる
int lengthSquared(Point p)
{
// pushl %ebp
// movl %esp, %ebp
int x = p.x;
// movl 12(%ebp), %edx ← 構造がわかるから
1命令でアクセスできる
int y = p.y;
// movl 8(%ebp), %eax
// leave
int xx = x*x;
// imull %edx, %edx
int yy = y*y;
// imull %eax, %eax
int ret = xx + xx;
// addl %edx, %eax
return ret;
// ret 53
}
54. 復習 (3/3)
JS は動的型付けの言語
// x と y がプロパティ
function Point(x0, y0) {
this.x = x0;
this.y = y0;
}
// name と x と y がプロパティ
function Item(name, x0, y0) {
this.name = name;
this.x = x0;
this.y = y0;
}
構造の違う二つのコンストラクタがあって・・・
54
55. 復習 (3/3)
JS は動的型付けの言語
?
// p のクラスはなに?
function lengthSquared(p) {
return p.x*p.x + p.y*p.y;
?
}
var pt
= new Point(10, 20);
var ptlensq = lengthSquared(pt);
var it
= new Item(quot;yakusouquot;, 10, 20);
var itlensq = lengthSquared(it);
55
56. 動的型付けの言語は
変数にクラス指定がない
オブジェクトごとのクラスはわかっても
●
変数のクラスは ( 調べるまで ) わからない
構造を仮定した高速化ができない
●
動的型付け言語一般の問題
●
J a va S c r ip t だけじゃない。
●
56
57. JS のプロパティアクセスは
素朴な
結局ハッシュ表検索 (+ 配列アクセス)
// 等価な C++ 風コード
// JS
var x = p.x; Object* x
= p->getProperty(X_NAME_ID);
...
Object*
Object::getProperty(int id)
{
Hash* h
= this->klass->m_propHash;
int index = h->lookup(id);
Property* p
= this->prop_array;
return p[index];
} 57
63. 予想が間違っていたら?
var pt = new Point(10, 20);
var it = new Item(quot;yakusouquot;, 10, 20);
for (var i=0; i<100; ++i) {
var p0lensq = lengthSquared(pt);
}
// こっちはたまにだよね?こっちがメインだった・・・
for (var i=0; i<100000; ++i) {
var p1lensq = lengthSquared(it);
...
}
63
64. 元のコードを書き換える !
// 等価な C++ 風コード
// JS
var x = p.x; if (p->klass == PointClass
ItemClass) {
return Point_GetX((int*)p);
return Item_GetX((int*)p);
} else {
return p->getProperty(...);
}
…
Object*
Item_GetX(int* p) {// 新たに生成
return p[2];
}
64
68. 各 VM 上での名前
V8 , S q uir r e lFis h Ext r e m e では
●
Po ly m o r p h ic In lin e Cac h in g
SELF 言語由来
●
J a va Hotspot VM でも利用
●
Tr a c e Mo nke y では
●
Tr ac e Tr ee
J a va Hotpath Re s e a r c h VM 由来
●
Tr a c ing 自体は Dynamo VM 由来
●
コアのアイデアはよく似ている
●
実現方法はちょっと違う 68
●
69. Polymorphic Inline Caching
コードの中 (Inline ) に
●
比較用のクラスを保存する (Ca c hing )
一つ以上のクラス (Po lym o r p hic ) を
●
保存する
if (p->klass == ItemClass) {
return Item_GetX((int*)p);
} else if (p->klass == PointClass) {
return Point_GetX((int*)p);
} else {
return p->getProperty(...);
}
69
70. Tracing Tree
バイトコードを実行しながら (Tr a c ing )
●
ひとつながりのネイティブコードを生成
コードがインライン化される
●
( メソッド呼び出しもインライン化 )
生成されたコード片は合流しない (Tr e e )
●
if (p->klass == ItemClass) {
return [(int*)p][2]; // inlined!
} else {
...
}
70
71. // 設定切替
ベンチマーク
var mono = false;
var n = 10000;
var arr = [];
for (var i=0; i<n; ++i) {
if (mono) {
arr.push(new Point(i, i)); mono
} else {
poly
arr.push((i%2) ? new Point(i, i) :
new Item(quot;itemquot;, i, i));
}
}
for (var i=0; i<n; ++i) {
for (var j=0; j<n; ++j) {
lengthSquared(arr[j]);
} 71
}
82. 今後の見所
ブラウザを含めたアプリの総合性能
●
FF1 1 ベンチ → g m a il ベンチ
●
モバイル機器での性能
●
消費メモリ
●
ARM CPU 向けの高速化
●
Int e rne t Exp lo re r の動向
●
今は遅すぎて話題にすらならず。
●
82
83. 観戦 HOWTO
とりあえずコードを読んでみよう
●
コア部分は 1 -2 万行程度
●
元ねたの論文を探して読もう
●
大抵コードよりわかりやすい
●
プロジェクトのブログを読もう
●
Mo zilla , We b kit, Chr o m e すべてあり
●
開発者自身のブログもあり
●
開発記録を読もう
●
ChangeLog 、 M L 、バグトラッカー
●
新機能もバグトラックで管理するのが定石
●
83
84. ブラウザ J a v a Sc r ip t 高速化
J IT バトル最終決戦
観戦ガイド
ご清聴ありがとうございました。
84
85. 写真たち
htt p ://f ic kr.c o m /p ho to s /d c jo hn/2 4 4 0 1 7 8 8 0 1 /
l
●
htt p ://f ic kr.c o m /p ho to s /s ri-h/2 8 6 6 4 5 8 7 4 7 /
l
●
htt p ://f ic kr.c o m /p ho to s /7 1 5 0 2 6 4 6 @ N0 0 /2 7 7 6 9 0 1 8 2 2 /
l
●
htt p ://f ic kr.c o m /p ho to s /a llis o nje nning s /2 5 0 3 4 1 0 2 1 3 /
l
●
htt p ://f ic kr.c o m /p ho to s /g r e e nmys t/1 4 6 8 7 6 0 7 9 1 /
l
●
85