view Slide/Slide.html @ 23:58dd8e127e4b

update paper & Slide
author e165727 <e165727@ie.u-ryukyu.ac.jp>
date Sun, 16 Feb 2020 20:49:19 +0900
parents b96b3244307b
children 27f7561b1135
line wrap: on
line source






<!DOCTYPE html>
<html>
<head>
   <meta http-equiv="content-type" content="text/html;charset=utf-8">
   <title>Raku(Perl6)のサーバーを使った高速実行</title>

   <meta name="generator" content="Slide Show (S9) v4.0.1 on Ruby 2.3.7 (2018-03-28) [universal.x86_64-darwin18]">
   <meta name="author"    content="Kouki Fukuda, Shinji Kono" >

<!-- style sheet links -->
<link rel="stylesheet" href="s6/themes/projection.css"   media="screen,projection">
<link rel="stylesheet" href="s6/themes/screen.css"       media="screen">
<link rel="stylesheet" href="s6/themes/print.css"        media="print">
<link rel="stylesheet" href="s6/themes/blank.css"        media="screen,projection">

<!-- JS -->
<script src="s6/js/jquery-1.11.3.min.js"></script>
<script src="s6/js/jquery.slideshow.js"></script>
<script src="s6/js/jquery.slideshow.counter.js"></script>
<script src="s6/js/jquery.slideshow.controls.js"></script>
<script src="s6/js/jquery.slideshow.footer.js"></script>
<script src="s6/js/jquery.slideshow.autoplay.js"></script>

<!-- prettify -->
<link rel="stylesheet" href="scripts/prettify.css">
<script src="scripts/prettify.js"></script>

<script>
  $(document).ready( function() {
    Slideshow.init();

    $('code').each(function(_, el) {
      if (!el.classList.contains('noprettyprint')) {
        el.classList.add('prettyprint');
      }
    });
    prettyPrint();
  } );

</script>

<!-- Better Browser Banner for Microsoft Internet Explorer (IE) -->
<!--[if IE]>
<script src="s6/js/jquery.microsoft.js"></script>
<![endif]-->

    

</head>
<body>

<div class="layout">
  <div id="header"></div>
  <div id="footer">
    <div align="right">
      <img src="s6/images/logo.svg" width="200px">
    </div>
  </div>
</div>

<div class="presentation">

  <div class='slide cover'>
    <table width="90%" height="90%" border="0" align="center">
      <tr>
        <td>
          <div align="center">
              <h1><font color="#808db5">Raku(Perl6)のサーバーを使った高速実行</font></h1>
          </div>
        </td>
      </tr>
      <tr>
        <td>
          <div align="left">
              Kouki Fukuda, Shinji Kono
              並列信頼研
            <hr style="color:#ffcc00;background-color:#ffcc00;text-align:left;border:none;width:100%;height:0.2em;">
          </div>
        </td>
      </tr>
    </table>
  </div>



<div class='slide'>
  
<!-- _S9SLIDE_ -->
<h2 id="スクリプト言語の高速実行">スクリプト言語の高速実行</h2>
<ul>
  <li>現在多くのスクリプト言語はインタプリタ型言語であり, 実行時にインタプリタの立ち上げ, モジュールを読み込み, スクリプトの解釈, スクリプトの実行 といったような処理を担っている.</li>
  <li>これらの処理の中にはOS上で事前に行うことで, より起動時間, 及び処理時間の短縮が予想されるものもある.</li>
  <li>頻繁にコードを書き換え実行するスクリプト言語では起動時間をできるだけ短くしたい.</li>
  <li>その手法として同一ホスト内で終了せずに実行を続けるサーバープロセスを立ち上げ, このサーバープロセス上で立ち上げておいたコンパイラに実行するファイル名を転送し, サーバー上でコンパイルを行う手法を提案する</li>
  <li>この提案手法に沿って『Abyss サーバー』を実装した.</li>
  <li>またスクリプト言語の速度改善を行うにあたり, 本研究では Raku というスクリプト言語を用いた.</li>
</ul>

<!-- 
## 研究概要
- Raku の実装の一つであるRakudoは、Byte code である MoarVM と、それ上で動作する Raku のsubsetであるnqp (Not Quite Perl)上に構成されている。
- 現状のRakuの実行はRakuで記述されたコンパイラをloadしてJITしながら実行すること自体に時間がかかっている。
- そこで, 同一ホスト内で終了せずに実行を続けるサーバープロセスを立ち上げ, このサーバープロセス上で立ち上げておいたコンパイラに実行するファイル名を転送し, サーバー上でコンパイルを行う手法を提案し実装する.
-->



</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="raku-と他言語の起動時間の比較">Raku と他言語の起動時間の比較</h2>
<ul>
  <li>Raku と他言語の起動時間の比較行なった.</li>
</ul>

<!--
- 実行環境
```
macOS Mojave version 10.14.5
メモリ8GB
プロセッサ2.7GHz Intel Core i5
```
-->

<ul>
  <li>perl5,ruby,raku,pythonでhelloworldを出力するプログラムを用いて行なった実行結果である.</li>
</ul>
<table style="border-collapse: collapse;" border="1" width="400" height="300">
    <tr>
        <th>Language</th>
        <th>Version</th>
        <th>Time</th>
        <th>Ratio</th>
    </tr>
    <tr>
        <td>raku</td>
        <td>2019.03.1</td>
        <td>249 ms</td>
        <td>62.25</td>
    </tr>
    <tr>
        <td>perl5</td>
        <td>v5.18.4</td>
        <td>4 ms</td>
        <td>1</td>
    </tr>
    <tr>
        <td>python</td>
        <td>2.7.10</td>
        <td>13 ms</td>
        <td>3.25</td>
    </tr>
    <tr>
        <td>ruby</td>
        <td>2.3.7p456</td>
        <td>83 ms</td>
        <td>20.75</td>
    </tr>
</table>

<p>Perl5 を基準とすると Raku はその62.25倍と非常に起動時間が遅いことがわかる.</p>

<!--
## Rakudo
- Rakudoとは現在のRakuの主力な実装である.(Raku は言語名, Rakudo はコンパイラ)
- Rakudo は MoarVM, と NQP と呼ばれる Raku のサブセット, NQP と Raku 自身で記述された Raku という構成である.
- Rakudo は MoarVMの他に JVM やJava Script を動作環境として選択可能である.

![](fig/Rakudo.svg)
- Rakudoの構成
-->

<!--
## NQP
- NQPとはNot Quite Perl の略で Raku のサブセットである.
- 基本的な文法などは Raku に準拠しているが, 変数を束縛で宣言するなどの違いがある.
- NQPコンパイラ自身もNQPで記述されている
- NQP は MoarVM や JVMの違いを吸収してAPIを提供している
-->

<!--
## MoarVM
- MoarVM は Raku に特化したVM 
- C 言語で実装されている
- JIT コンパイルなどが現在導入されているが, 起動時間などが低速である問題がある
-->

<!--
## Perl6 の名称変更
- Raku はPerlの次期メジャーバージョンとして設計が始められ, 元々Perl6という名称であったが, Perl6 は言語仕様及び処理実装が Perl5 と大幅に異なっており, 言語的な互換性が存在しないため別名がつけられました.
- 現在有力な処理系である Rakudo から名前を取り Raku という別名がつけられた.

## Rakudoの語源
- ちなみに Rakudo の語源は, 楽土と駱駝道で
- 楽土の方は日本語で「楽園」という意味で
- 駱駝道の方は Perlのマスコットキャラクターが🐪だったからです
    - http://blogs.perl.org/users/zoffix_znet/2017/07/the-hot-new-language-named-rakudo.html
-->



</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="rakuが遅い理由">Rakuが遅い理由</h2>
<ul>
  <li>通常 Ruby のようなスクリプト言語ではまず YARV などのプロセスVM が起動し,その後スクリプトを Byte code に変換して実行という手順を踏む.</li>
  <li>Rakudo はインタプリタの起動時間及び, 全体的な処理時間が他のスクリプト言語と比較して低速である.</li>
  <li>これは Rakudo 自体が Raku と NQP で書かれているため, MoarVMを起動し, Rakudo と NQP のByte codeを読み取り, Rakudoを起動し, その後スクリプトを読み取り, スクリプトの Byte code 変換というような手順で進むためである.</li>
  <li>また Raku は実行する際に実行時の情報が必要であり, メソッドを実行する際に invoke が走ることも遅い原因である.
    <ul>
      <li>invoke はMoarVM の method 呼び出しのbyte codeです.</li>
    </ul>
  </li>
</ul>



</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="raku-による-abyss-server-の実装">Raku による Abyss Server の実装</h2>
<ul>
  <li>提案手法に沿い『Abyss Server』を実装した.</li>
  <li>Abyss Server はUnix domain socketを用いて送信した Raku スクリプトを実行するための Server である.</li>
  <li>下記の図は, Abyss Server を用いたスクリプト言語の実行手順です.</li>
</ul>

<p><img src="fig/Abyss.svg" alt="" /></p>

<!--
## Raku の Unix domain socket 実装
- Unix domain socket でなくINET で実装した場合, 他者からスクリプトを送りつけられる可能性がある.
    - そのため今回はUnix domain socket を用いて実装しました.
- Rakuには現在Unix domain socketの実装がないため, Unix domain socket の実装を行なった.
- IO::Socketがroleとして定義されている
    - Raku での role は他の言語の interface に相当するものである
- 現状 Raku にはIO::Socket::INETとIO::Socket::Asyncの実装がある
    - 先ほど上で説明したようにINETとAsyncはセキュリティの問題で使えない
- IO::Socketを実装した IO::Socket::Unix を実装した
    - IO::Socket::Unixの中ではnqpの機能を使う必要がある
-->



</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="通常実行と提案手法の速度比較">通常実行と提案手法の速度比較</h2>
<ul>
  <li>今回は,提案手法での実行速度と通常実行での実行速度, この二つの速度の比較を行う</li>
  <li>題材として行うのはhelloworldを出力するだけのプログラムとフィボナッチ数列の例題である.</li>
</ul>



</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="予測">予測</h2>
<ul>
  <li>前述した通り, Raku はコンパイラの起動に時間がかかっているため, 提案手法を用いることで起動時間分早く実行することができると予測する.</li>
</ul>



</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="実行結果">実行結果</h2>

<ul>
  <li>通常実行
    <ul>
      <li>0.2695 sec</li>
    </ul>
  </li>
  <li>提案手法
    <ul>
      <li>0.0238 sec</li>
    </ul>
  </li>
  <li>提案手法は通常実行に比べて約10倍早い実行結果になった</li>
</ul>



</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="フィボナッチ数列の例題">フィボナッチ数列の例題</h2>

<ul>
  <li>通常実行
    <ul>
      <li>0.2128 sec</li>
    </ul>
  </li>
  <li>提案手法
    <ul>
      <li>0.0415 sec</li>
    </ul>
  </li>
  <li>先ほどと同様,提案手法は通常実行に比べて早い結果となり,約5倍早い実行結果になった</li>
</ul>



</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="abyss-server側の実装">Abyss Server側の実装</h2>
<ul>
  <li>Abyss Server は起動すると, まず自身にファイルパスを転送するためのソケットを生成し, その後ファイルを受け取るための待機ループに入る.</li>
  <li>ファイルパスを受け取ると, ファイルを開き実行する.</li>
</ul>

<pre><code>sub close(int32) returns int32 is native { ... }
sub dup(int32 $old) returns int32 is native { ... }
sub dup2(int32 $new, int32 $old) returns int32 is native { ... }

method readeval 
{
    my $listen = IO::Socket::Unix.new(  :listen,
                                        :localhost&lt;localhost&gt;,
                                        :localport(3333) );            
    my $backup = dup(1);
    say DateTime.now;

    loop
    {
        my $conn = $listen.accept;
        my $sock_msg;
        my $buf = $conn.recv();
        $sock_msg = $buf;
        close(1);
        dup2($conn.native-descriptor(), 1);
        EVALFILE $sock_msg;
        dup2($backup, 1);
        close($backup);
        $conn.close;
    }

    $listen.close;
}
</code></pre>



</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="abyss-client側の実装">Abyss Client側の実装</h2>
<ul>
  <li>ユーザーは Abyss Server を起動後,ファイルパスをサーバーに送信する.</li>
</ul>

<pre><code>my $conn = IO::Socket::Unix.new( :host&lt;localhost&gt;,
                                 :port(3333) );

$conn.print: 'Absolute file path';

my $sock_msg;

while my $buf = $conn.recv(:bin)
{
    $sock_msg = $buf.decode;
    last;
}

say $sock_msg;
</code></pre>



</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="raku-のeval">Raku のEVAL</h2>
<ul>
  <li>Raku では EVAL 関数があり文字列を Raku のソースコード自身として評価できる</li>
  <li>Raku では, EVAL は通常は使用できないようになっており, MONKEY-SEE-NO-EVAL という pragma を実行することで使うことができるようになる.</li>
</ul>

<pre><code>use MONKEY-SEE-NO-EVAL;

EVAL "say { 5 + 5 }";   # OUTPUT: 10
</code></pre>

<ul>
  <li>EVALFILEはファイルパスを受け取ると, ファイルの中身をバイト文字列に変換し, それをEVALと同様に解釈する.</li>
</ul>



</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="abyss-serverの利点">Abyss Serverの利点</h2>
<ul>
  <li>Abyss Serverを用いて実行することで, サーバー上で事前に起動した Rakudo を再利用し, 投げられた Raku スクリプトの実行を行うため, Rakudo の起動時間を短縮できる.
    <ul>
      <li>約10倍早くなる</li>
    </ul>
  </li>
  <li>一度投げられたスクリプトのバイトコード, もしくは計算結果をキャッシュで保存しておき, 再度実行する際に, そのキャッシュを用いてコンパイル時間を省くような仕組みを入れやすいと考えられる.</li>
  <li>他の起動時間遅いスクリプト言語や, モジュールの読み込みが遅い言語などにも, 応用しやすいと考えられる.</li>
  <li>普通のスクリプト言語だと実行するたびにforkして実行しインタプリタの立ち上げという処理になるが, プロセス毎回起動しなくて済む</li>
</ul>



</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="abyss-serverの欠点">Abyss Serverの欠点</h2>
<ul>
  <li>現在 Abyss Server には 一度スクリプトを実行した後にサーバー内の環境をリセットする機能が存在しないため,スクリプトがサーバー内の環境に影響を及ぼした場合,通常実行と違う挙動をする危険性がある</li>
  <li>同時に二つ以上のタスクを与えられると実行順のスケジューリングができない</li>
  <li>異常に長いタスクが投げられた場合, 次のタスクが前のタスクが終わるまで実行ができない</li>
  <li>起動時のオプションが選択出来ない</li>
</ul>



</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="os上でスクリプト言語を実行する方法の改善点">OS上でスクリプト言語を実行する方法の改善点</h2>
<ul>
  <li>OS上でスクリプト言語を実行する際の最適な方法として,提案手法のように事前に起動したコンパイラを再利用する方法は有効であると考える</li>
  <li>またOS上でスクリプト言語を実行する際に, OS側で用意されてあるべきAPIとしては以下のようなものが挙げられる
    <ul>
      <li>提案手法のように一度立ち上げられたインタプリタを立ち上げたままにする機能</li>
      <li>複数回投げられたスクリプトの実行結果もしくはbasic block を保存できる機能</li>
      <li>実行するスクリプトの周りにあるJsonファイルをあらかじめParseしておく機能</li>
    </ul>
  </li>
</ul>



</div>

<div class='slide'>
  <!-- _S9SLIDE_ -->
<h2 id="まとめと今後の課題">まとめと今後の課題</h2>
<ul>
  <li>スクリプト言語 Raku の新たな実行方法の提案,及び提案手法に添って「Abyss Server」の実装を行なった.</li>
  <li>Raku にUnix domain socket の実装を行なった.</li>
  <li>Raku の速度改善において, 同一ホスト内でサーバープロセスを生成し,サーバープロセス内であらかじめコンパイラを立ち上げて起き, 実行するファイル名を転送し,サーバープロセス上でコンパイルを行う手法は有効であると考えられる</li>
  <li>また今後今後の課題としては以下のようなものが挙げられる
    <ul>
      <li>一度投げられたスクリプトをキャッシュで保存しておき,再度実行する際に,そのキャッシュを用いてコンパイル時間を省くような仕組み</li>
      <li>複数タスクが投げられた場合の処理の実装</li>
    </ul>
  </li>
</ul>

</div>


</div><!-- presentation -->
</body>
</html>