Perlと出会い、Perlを作る     株式会社ミクシィ Masaaki Goshima(@goccy54)
Perl作成を決意• 「深く理解したいなら作る」という  モットーのもと、学ぶなら作って学びた  い! – どうせなら、スクリプト言語界最速のPerlを作りたい
gperl• 世界一高速なPerl処理系を目指している• 大目標はPerl5.16とある程度互換性を持  ち, mixiのホーム画面を表示させるスクリプ  ト(home.pl)を動かすこと• C++でスクラッチから実装 – 依存ライブラリは極力...
アジェンダ•   gperlの概要と性能評価•   高速化技術あれこれ•   高速化のために断念したPerlの仕様•   まとめ
gperlの概要(Speed)• 導入済みの高速化技術 – asmベースの2番地コード命令 – Register型VM – Direct Threaded Codeを用いた   高速関数呼び出し – 引数オブジェクトの事前構築 – NaN-bo...
gperlの概要(Syntax)• サポートされている文法やデータ構造 – データ型 :   int, double, String, Array(Ref), Hash(Ref), CodeRef, B   lessedObject – ループ...
性能評価(1/3)                      Fibonacci数列の計算N=35       Language          time(real)[sec]   X(倍率)        gperl(JIT)       ...
性能評価(2/3)                  たらい回し関数の計算(x,y,z) = (13, 6, 0)       Language           time(real)[sec]   X(倍率)        gperl(JI...
性能評価(3/3)                         binary-treesN=15       Language          time(real)[sec]   X(倍率)         v8(0.8.0)      ...
高速化技術あれこれ
引数オブジェクトの事前構築(1/2)• 引数格納用の配列を事前構築して高速化 – Perlは, シンプルに実装すると関数呼び出しのた   びに引数用の配列オブジェクトが作られる  • 関数呼び出しの度に配列を生成すると遅い – 通常、引数の数は...
引数オブジェクトの事前構築(2/2)                                        関数呼び出しスタックの一つ一つに対応して                           ・・・・関数呼び出しスタック   ...
NaN-boxingによる型検査(1/2)• Perlのような動的型付け言語は、変数の型を保  存する仕組みが必要 – 通常は、値(int, double, boolean)であっても、オブ   ジェクトとして扱い、型情報を持たせる(boxin...
NaN-boxingによる型検査(2/2)• NaN-boxingは、double型のNaN領域に型  情報を埋め込む技術  – unboxingと同じように扱えて、型情報も持た    せられる               unboxingされ...
アノテーションによる  Static Typing/JIT Compileの実現• 大規模開発を行う場合、型は静的に決定できる  場合がほとんど – 型安全性が損なわれるとバグのもとに – そもそも、開発するときに型のイメージはあるはず• 型を...
アノテーションによる   Static Typing/JIT Compileの実現• 関数の宣言前に、”#@static_typing” or  “#@jit_safe”と記述することで、静的型付け用の命  令やJIT用の命令が生成される – ...
高速化のために断念した(い)機能
高速化のために断念した(い)機能1. 関数引数にあるリストの展開2. デフォルトでのスカラー変数の参照渡し
1.関数引数にあるリストの展開• Perlでは, 関数の引数にリストがあるときは, 中  身を展開して一つの配列にしてから関数に渡す – 配列結合のSyntax SugarがPerlでは(@a, @b)で表現   でき、引数では常に有効になる ...
1.関数引数にあるリストの展開• gperlではあらかじめ引数の数を想定して引数ス  タックのサイズを決めているため、引数の数が  多いとスタックを拡張しなければならない                                     ...
2.デフォルトでのスカラー変数の        参照渡し• Perlでは、関数の引数は全て参照渡しになるの  で、明示的にリファレンスにしなくとも、値の  書き変えが可能subf{                           NaN-b...
まとめ• VM、GCやJITなど、ベースとなる技術の  設計や実装はできてきた• 今後の予定 (文法や機能の充実) – 後置文, 三項演算子, format, 正規表現 ,   map/grep, eval, use/FFI, 継承, 括弧の省...
https://github.com/goccy/gperl
Perlと出会い、Perlを作る
Upcoming SlideShare
Loading in...5
×

Perlと出会い、Perlを作る

3,198

Published on

Published in: Technology

Perlと出会い、Perlを作る

  1. 1. Perlと出会い、Perlを作る 株式会社ミクシィ Masaaki Goshima(@goccy54)
  2. 2. Perl作成を決意• 「深く理解したいなら作る」という モットーのもと、学ぶなら作って学びた い! – どうせなら、スクリプト言語界最速のPerlを作りたい
  3. 3. gperl• 世界一高速なPerl処理系を目指している• 大目標はPerl5.16とある程度互換性を持 ち, mixiのホーム画面を表示させるスクリプ ト(home.pl)を動かすこと• C++でスクラッチから実装 – 依存ライブラリは極力入れない方針 • (readlineも自作)
  4. 4. アジェンダ• gperlの概要と性能評価• 高速化技術あれこれ• 高速化のために断念したPerlの仕様• まとめ
  5. 5. gperlの概要(Speed)• 導入済みの高速化技術 – asmベースの2番地コード命令 – Register型VM – Direct Threaded Codeを用いた 高速関数呼び出し – 引数オブジェクトの事前構築 – NaN-boxingによる型検査 – アノテーションによるStatic Typingの実現 – JIT Compile
  6. 6. gperlの概要(Syntax)• サポートされている文法やデータ構造 – データ型 : int, double, String, Array(Ref), Hash(Ref), CodeRef, B lessedObject – ループ: for, while, foreach – 条件文: if-elsif-else – 関数呼び出し(再帰処理可)とクラス作成(package) – 演算子(一部) : +, -, *, /, +=, -=, ++, -- , <<, >>, <, >, <=, >=, !=, == – その他: ローカル変数, 複数変数の宣言と代入など
  7. 7. 性能評価(1/3) Fibonacci数列の計算N=35 Language time(real)[sec] X(倍率) gperl(JIT) 0.10 X91.2 測定環境 LuaJIT(2.0.0-beta10) 0.12 X76.0 v8(0.8.0) 0.18 X50.6 MacOSX(10.7.4) 2.2GHz Intel Core i7 gperl(StaticTyping) 0.44 X20.7 Memory: 8GB gperl 0.46 X19.8 Darwin Kernel Version 11.4.0 x86_64 Konoha(1.0) 0.52 X17.5 PyPy(1.9.0) 0.53 X17.2 SpiderMonkey(1.8.5) 2.17 X4.2 Lua(5.2.1) 2.82 X3.2 測れるもの Ruby(1.9.3) 3.65 X2.5 数値演算速度 Python(2.7.3) 4.32 X2.1 関数呼び出し速度 VM設計の良し悪し Perl(5.16.0) 9.12 X1.0
  8. 8. 性能評価(2/3) たらい回し関数の計算(x,y,z) = (13, 6, 0) Language time(real)[sec] X(倍率) gperl(JIT) 0.29 X102.0 測定環境 v8(0.8.0) 0.41 X72.1 LuaJIT(2.0.0-beta10) MacOSX(10.7.4) 0.46 X64.3 2.2GHz Intel Core i7 gperl(StaticTyping) 1.24 X23.9 Memory: 8GB Darwin Kernel Version Konoha(1.0) 1.38 X21.4 11.4.0 x86_64 gperl 1.56 X19.0 PyPy(1.9.0) 4.30 X6.9 SpiderMonkey(1.8.5) 5.70 X5.2 測れるもの Lua(5.2.1) 5.97 X5.0 複数引数の処理 Ruby(1.9.3) 7.63 X3.9 数値演算速度 関数呼び出し速度 Python(2.7.3) 17.18 X1.7 VM設計の良し悪し Perl(5.16.0) 29.59 X1.0
  9. 9. 性能評価(3/3) binary-treesN=15 Language time(real)[sec] X(倍率) v8(0.8.0) 0.32 X35.8 測定環境 LuaJIT(2.0.0-beta10) 1.29 X8.9 MacOSX(10.7.4) Konoha(1.0) 1.46 X7.9 2.2GHz Intel Core i7 Memory: 8GB PyPy(1.9.0) 1.98 X5.8 Darwin Kernel Version Python(2.7.3) 2.25 X5.1 11.4.0 x86_64 gperl(Static Typing) 3.97 X2.9 gperl 4.06 X2.8 Ruby(1.9.3) 5.23 X2.2 SpiderMonkey(5.7.3) 5.73 X2.0 測れるもの Lua(5.2.1) 7.56 X1.5 GCの速度 Perl(5.16.0) 11.47 X1.0
  10. 10. 高速化技術あれこれ
  11. 11. 引数オブジェクトの事前構築(1/2)• 引数格納用の配列を事前構築して高速化 – Perlは, シンプルに実装すると関数呼び出しのた びに引数用の配列オブジェクトが作られる • 関数呼び出しの度に配列を生成すると遅い – 通常、引数の数は一定数以下に抑えられてコー ディングされるため、あらかじめ引数用の配列を 確保しておくことで対処する
  12. 12. 引数オブジェクトの事前構築(2/2) 関数呼び出しスタックの一つ一つに対応して ・・・・関数呼び出しスタック 引数用の配列を事前に作り、引数はそこに積まれるスタックの伸びる方向 3 4 5 1 :subf { 2 : my $a = $_[0]; 2 3 4 引数用の配列 3 : my$b= $_[1]; 4 : my$c= $_[2]; 1 2 3 5 : if ($a > 10) { 6 : return 1; 7 : } 8 : returnf(++$a, ++$b, ++$c); 9 :} 関数が呼ばれるとstack_topが一つ上がる 10 :f(1, 2, 3); 関数から抜けると一つ下がる しかしPerlには、引数が一定数以下に抑えられるという常識が通じない 仕様があるため、一筋縄ではいかない =>後述
  13. 13. NaN-boxingによる型検査(1/2)• Perlのような動的型付け言語は、変数の型を保 存する仕組みが必要 – 通常は、値(int, double, boolean)であっても、オブ ジェクトとして扱い、型情報を持たせる(boxing) – しかしboxingしてあると、計算の時に毎回オブジェク トから値を取り出す操作(unboxing)が入るため遅い. また、全てオブジェクトにするためメモリ効率も悪 くなる case ADD: structIntObject { Object *a = reg[0]; Object *b = reg[1]; inttype; //型情報 if (a->type == TypeInt&&b->type == TypeInt) { intdata; //実際の値 ((IntObject *)a)->data += ((IntObject *)b)->data; }; } else if (a->type == TypeString&&b->type == TypeString) { …… }
  14. 14. NaN-boxingによる型検査(2/2)• NaN-boxingは、double型のNaN領域に型 情報を埋め込む技術 – unboxingと同じように扱えて、型情報も持た せられる unboxingされている case ADD: のに型検査できるunion{ switch (typecheck(reg[0], reg[1])) {intidata; caseInt_Int:double ddata; reg[0].idata += reg[1].idata;//データに直にアクセスできるchar *sdata; break;void *odata; case String_String:}; ….. }しかしPerlには、関数呼び出し時に渡される変数は全てリファレンスとして扱われるという仕様があるため、一筋縄ではいかない =>後述
  15. 15. アノテーションによる Static Typing/JIT Compileの実現• 大規模開発を行う場合、型は静的に決定できる 場合がほとんど – 型安全性が損なわれるとバグのもとに – そもそも、開発するときに型のイメージはあるはず• 型を静的に決められるケースが多いなら、その 恩恵を受けようじゃないか – アノテーションを付加することで、静的型付け用の命 令を生成したり, JIT Compileできるようにする
  16. 16. アノテーションによる Static Typing/JIT Compileの実現• 関数の宣言前に、”#@static_typing” or “#@jit_safe”と記述することで、静的型付け用の命 令やJIT用の命令が生成される – #~とすることで、Perlとの互換性を保つ 1: #@static_typing 2: subfib {型が決まらないと処理できない 3: if ($_[0] < 2) { 命令において、 4: return 1;初めて処理した時に分かった型 5: } else { を覚えておき、 6: return fib($_[0] - 1) + fib($_[0] - 2); 2回目からは分かった型用の 7: } 命令で処理する 8:} 9:print(fib(35), "n");
  17. 17. 高速化のために断念した(い)機能
  18. 18. 高速化のために断念した(い)機能1. 関数引数にあるリストの展開2. デフォルトでのスカラー変数の参照渡し
  19. 19. 1.関数引数にあるリストの展開• Perlでは, 関数の引数にリストがあるときは, 中 身を展開して一つの配列にしてから関数に渡す – 配列結合のSyntax SugarがPerlでは(@a, @b)で表現 でき、引数では常に有効になる subf{ my@args= @_; print $args[0], "n"; # $args[0] == 1 print $args[1], "n"; # $args[1] == 2 } my@a = (1, 2, 3); my @b= (4, 5, 6); f(@a, @b);
  20. 20. 1.関数引数にあるリストの展開• gperlではあらかじめ引数の数を想定して引数ス タックのサイズを決めているため、引数の数が 多いとスタックを拡張しなければならない gperl内部では@aも一つのsubf{ 配列オブジェクトとして扱わmy@args= @_; れているため、そのままだとprint $args[0], "n"; # $args[0] == @a $args[0]の値は@aになり、print $args[1], "n"; # $args[1] == @b $args[1]の値は@bになって} しまうmy@a = (1, 2, 3);my @b= (4, 5, 6); これを簡単に避けるために、f(@a, @b); リストを展開・結合したい場 合は、f((@a, @b))のように呼 び出すルールを決めている
  21. 21. 2.デフォルトでのスカラー変数の 参照渡し• Perlでは、関数の引数は全て参照渡しになるの で、明示的にリファレンスにしなくとも、値の 書き変えが可能subf{ NaN-boxingではこの挙動を $_[0] = 3; 再現できないため、} $_[0]には$aの スカラー変数のデフォルトでの リファレンスが入っ 参照渡しは未サポートmy $a = 1; ているので、値を書f($a); き変えると元の値も $aを使ってリファレンスをprint $a, "n”; 書き変わる 渡すことを明示すれば、 そのときにboxingを行って対処する
  22. 22. まとめ• VM、GCやJITなど、ベースとなる技術の 設計や実装はできてきた• 今後の予定 (文法や機能の充実) – 後置文, 三項演算子, format, 正規表現 , map/grep, eval, use/FFI, 継承, 括弧の省略など – ドキュメントの整備• 研修時に書いたPerlスクリプトがやっと動く ように・・ – 本当の意味で研修内容を理解できた・・・!?
  23. 23. https://github.com/goccy/gperl
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×