view Paper/koo.tex @ 4:d33d89b2dce4

コメント用原稿提出
author e165727 <e165727@ie.u-ryukyu.ac.jp>
date Fri, 08 Nov 2019 21:39:33 +0900
parents 3926216e699f
children 8bdae210d08d
line wrap: on
line source

% withpage: ページ番号をつける (著者確認用)
% english: 英語原稿用フォーマット
\documentclass{ipsjprosym}
%\documentclass[withpage, english]{ipsjprosym}

\usepackage[dvipdfmx]{graphicx}
\usepackage{latexsym}
\usepackage{comment}
\usepackage{listings}
\usepackage{here}
\lstset{
  language=C, 
  tabsize=2, 
  frame=single, 
  basicstyle={\tt\footnotesize}, % 
  identifierstyle={\footnotesize}, % 
  commentstyle={\footnotesize\itshape}, % 
  keywordstyle={\footnotesize\ttfamily}, % 
  ndkeywordstyle={\footnotesize\ttfamily}, % 
  stringstyle={\footnotesize\ttfamily}, 
  breaklines=true, 
  captionpos=b, 
  columns=[l]{fullflexible}, % 
  xrightmargin=0zw, % 
  xleftmargin=1zw, % 
  aboveskip=1zw, 
  numberstyle={\scriptsize}, % 
  stepnumber=1, 
  numbersep=0.5zw, % 
  lineskip=-0.5ex, 
}
\renewcommand{\lstlistingname}{Code}
\usepackage{caption}
\captionsetup[lstlisting]{font={small, tt}}
\usepackage{url}
\begin{document}

% Title,  Author %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\title{Perl6のサーバを使った実行}

%\affiliate{IPSJ}{情報処理学会}
\affiliate{IERYUKYU}{琉球大学工学部情報工学科}

\author{福田 光希}{Kouki FUKUDA}{IERYUKYU}[k.fukuda@cr.ie.u-ryukyu.ac.jp]
\author{河野 真治}{Shinji KONO}{IERYUKYU}[kono@ie.u-ryukyu.ac.jp]

%概要
\begin{abstract}
Perl6 の実装の一つであるRakudoは, Byte code である MoarVM と, その上で動作する Perl6 のsubsetである nqp (Not Quite Perl) 上に構成されている,

現状の Perl6 の実行は Perl6 で記述されたコンパイラを load して JIT しながら実行すること自体に時間がかかっている.
そこで, Perl6 をサーバーとして動作させ, 実行するファイルをサーバーに投げて実行する方法を実装してみた.

本論文では, サーバーで script 言語を実行する場合の利点と欠点について考察する.
\end{abstract}

\begin{jkeyword}
プログラミング言語, Perl6, サーバー, Raku 
\end{jkeyword}

\maketitle

% Body %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Perl6 の起動時間の改善}
現在開発の進んでいる言語に Perl6 がある.
スクリプト言語 Perl6 は任意の VM が選択できるようになっており, 主に利用されている VM に C で書かれた MoarVM が存在する. 
MoarVM は JIT コンパイルなどをサポートしているが, 全体的な起動時間及び処理速度が Perl5 や Python , Ruby などの他のスクリプト言語と比較し非常に低速である.
その為, 現在日本国内では Perl6 は実務としてあまり使われていない.

Perl6 の持つ言語機能や型システムは非常に柔軟かつ強力であるため, 実用的な処理速度に達すれば, 言語の利用件数が向上することが期待される.
Perl6 は MoarVM に基づくJIT コンパイラを持っており,コンパイルされた結果はプロセッサが実行可能な機械語に相当する.

しかし現状の Perl6 は起動時間が非常に遅いことが問題である.

この問題を解決するために, 実行するファイル名をサーバーに転送し,サーバー上であらかじめ立ち上げておいたコンパイラでコンパイルを行う手法を提案する.

またサーバーでは,サーバーに投げられた Perl6 をコンパイラで実行する際に, そのスクリプトが次に実行するスクリプトに影響を与えないことを保証する必要がある.
この問題を解決するために,本研究ではサーバーのコンテナ化を行う.

研究をするにあたり得られた, サーバー上でscript言語を実行する場合の利点と欠点について述べ, 今後の展望について記載する.

\section{Perl6}
Perl6 は 2002 年に LarryWall が Perl を置き換える言語として設計を開始した. Perl5 の言語的な問題点であるオブジェクト指向機能の強力なサポートなどを取り入れた言語として設計された. Perl5 は設計と実装が同一であり, Larry らによって書かれた C 実装のみだった. Perl6 は設計と実装が分離している. 言語的な特徴としては, 独自に Perl6 の文法を拡張可能な Grammar, Perl5 と比較した場合のオブジェクト指向言語としての進化も見られる. また Perl6 は漸進的型付け言語である. 従来の Perl の様に変数に代入する対象の型や, 文脈に応じて型を変更する動的型言語としての側面を持ちつつ, 独自に定義した型を始めとする様々な型に, 静的に変数の型を設定する事が可能である.
Perl6 は言語仕様及び処理実装が Perl5 と大幅に異なっており, 言語的な互換性が存在しない. 従って現在では Perl6 と Perl5 は別言語としての開発方針になっている. Perl6 は現在有力な処理系である Rakudo から名前を取り Raku という別名がつけられている.

Raku の現在の主流な実装は Rakudo である. Rakudo は MoarVM, と NQP と呼ばれる Raku のサブセット, NQPと Raku 自身で記述された Raku という構成である.
MoarVM は NQP と Byte Code を解釈する. 

NQP とは Not Quite Perl の略で Raku のサブセットである. その為基本的な文法などは Raku に準拠しているが, 変数を束縛で宣言するなどの違いが見られる.

この NQP で記述された Raku の事を Rakudo と呼ぶ.
Rakudo は MoarVM の他に JVM , Javascript を動作環境として選択可能である.

Raku の起動は, MoarVM を起動, NQP をロード, Rakudo をロードもしくはコンパイルし, その後 JIT しながら実行する.

\begin{figure}[H]
     \begin{center}
     \includegraphics[width=70mm]{images/Rakudo.pdf}
     \end{center}
     \caption{Rakudoの構成}
    \label{fig:perl6cbcinter}
\end{figure}

\subsection{MoarVM}

MoarVM は Raku に特化した VM である. C 言語で実装されている. JIT コンパイルなどが現在導入されているが, 起動時間などが低速である問題がある. MoarVM 独自の ByteCode があり, NQP からこれを出力する機能などが存在している.

\section{NQP}
\begin{comment}
%NQP とは Raku のサブセットである.
%その為基本的な文法などは Raku に準拠しているが,変数を束縛で宣言するなどの違いが見られる.

%NQP は最終的には NQP 自身でブートストラップする言語であるが,ビルドの最初にはすでに書かれた MoarvM ByteCode を必要とする.
%この MoarVMByteCode の状態を Stage0 と言う.
%Raku の一部は NQP を拡張したもので書かれている為, Rakudo を動作させる為には MoarVM などの VM , VM に対応させる様にビルドした NQP がそれぞれ必要となる.
%NQP は与えられた Stage0 を使い Stage1 をビルドし, そのStage1 を利用し Stage2 をビルドする事で生成できる.
\end{comment}

RakudoにおけるNQPは現在MoarVM, JVM上で動作する.
NQPはPerl6のサブセットであるため, 主な文法などはPerl6に準拠しているが幾つか異なる点が存在する.
NQPは最終的にはNQP自身でブートストラップする言語であるが, ビルドの最初にはすでに書かれたMoarVMのバイトコードを必要とする.
このMoarVMのバイトコードの状態をStage0と言う.%い, バイトコードが付随するソースディレクトリ内のディレクトリ名として設定されている.
Perl6の一部はNQPを拡張したもので書かれている為, Rakudoを動作させる為にはMoarVMなどのVM, VMに対応させる様にビルドしたNQPがそれぞれ必要となる.
現在のNQPではMoarVM, JVMに対応するStage0はそれぞれMoarVMのバイトコード, jarファイルが用意されている.
MoarVMのModuleLoaderはStage0にあるMoarVMのバイトコードで書かれた一連のファイルが該当する.


Stage0にあるファイルをMoarVMに与えることで, NQPのインタプリタが実行される様になっている.
これはStage0の一連のファイルは, MoarVMのバイトコードなどで記述されたNQPコンパイラのモジュールである為である.
NQPのインタプリタはセルフビルドが完了すると, nqpというシェルスクリプトとして提供される.
このシェルスクリプトは, ライブラリパスなどを設定してMoarVMの実行バイナリであるmoarを起動するものである.
%NQPは6modelと呼ばれるオブジェクトモデルを採用としている.%が, これを構築する為に必要なNQPCORE,正規表現系のQRegex,MoarVMのModuleLoaderなどがMoarVMBytecodeで記述されている.これらMoarVMBytecodeの拡張子は.MoarVMである.
%MoarVMに対してStage0のディレクトリにライブラリパスを設定し, nqp.MoarVMを実行させることでnqpの対話型環境が起動する.

\begin{figure*}[ht]
     \begin{center}
     \includegraphics[width=140mm]{fig/tgraph.pdf}
     \end{center}
     \caption{NQPのビルドフロー}
    \label{fig:nqpbuild}
\end{figure*}

NQPのビルドフローを図\ref{fig:nqpbuild}に示す.
RakudoによるPerl6に処理系はNQPにおけるnqpと同様に, moarにライブラリパスなどを設定したperl6というシェルスクリプトである.
このperl6を動かすためにはself buildしたNQPコンパイラが必要となる.
その為にStage0を利用してStage1をビルドしNQPコンパイラを作成する.
Stage1は中間的な出力であり, 生成されたNQPファイルはStage2と同一であるが, MoarVMのバイトコードが異なる.
Perl6では完全なセルフコンパイルを実行したNQPが要求される為, Stage1を利用してもう一度ビルドを行いStage2を作成する.

Perl6のテストスイートであるRoastやドキュメントなどによって設計が定まっているPerl6とは異なりNQP自身の設計は今後も変更になる可能性が開発者から公表されている.
現在の公表されているNQPのオペコードはNQPのリポジトリに記述されているものである.


%\subsection{Rakudo Perl6}
%Rakudo実装上におけるPerl6はRakudo Perl6と呼ばれているGitリポジトリで管理されているプログラムのことである.
%前述した通りRakudo Perl6はPerl6のサブセットであるNQPを用いて記述されている.
%従ってyaccやlexと言ったPerl5の文字解析, 構文解析に利用していたプログラムは利用せず, NQP側で構文定義などを行っている.
%NQPはNQP自身でBootstrappingされている為, Rakudo Perl6のbuild時にはNQPの実行環境として要したVM, それに基づいてbuildしたNQPがそれぞれ必要となる.


\section{なぜ Perl6 は遅いのか}
通常 Ruby のようなスクリプト言語ではまず YARVなどのプロセスVM が起動し,その後スクリプトを Byte code に変換して実行という手順を踏む.
Rakudo はインタプリタの起動時間及び、 全体的な処理時間が他のスクリプト言語と比較して非常に低速である.
これは Rakudo 自体が Perl6 と NQP で書かれているため, MoarVMを起動し, Rakudo と NQP のByte codeを読み取り, Rakudoを起動し, その後スクリプトを読み取り, スクリプトの Byte code 変換というような手順で進むためである.
また Raku は実行時の情報が必要であり, メソッドを実行する際に invoke が走ることも遅い原因である.

\section{Perl6によるAbyssの実装}

提案手法で実装したAbyss サーバーは Perl6 で書かれているクライアント側から投げられた Perl6 を実行するためのサーバーである.
図3は Abyss サーバーを用いたスクリプト言語実行手順である. 
Abyss サーバーはユーザーがPerl6を直接立ち上げるのではなく,まず図3右側のAbyssサーバーを起動し,ユーザーはAbyssサーバーにファイルパスをソケット通信で送り,Abyssサーバーがファイルを開き実行し,その実行結果をユーザーに返す. 

この手法を用いることで, サーバー上で事前に起動した Rakudo を再利用し, 投げられた Raku スクリプトの実行を行うため, Rakudo の全体的な処理時間を短縮できると推測できる. 


\begin{figure}[H]
     \begin{center}
     \includegraphics[width=80mm]{images/abyss.pdf}
     \end{center}
     \caption{Abyssサーバーを用いたスクリプト言語実行手順}
    \label{fig:perl6cbcinter}
\end{figure}ccc

Code1はAbyss サーバーのソースコードである.
Abyssサーバーは起動すると,まず自身にファイルパスを転送するためのソケットを生成し,その後ファイルを受け取るための待機ループに入る.

Perl6ではEVAL関数[\ref{eval}]があり文字列をPerl6のソースコード自身として評価できる

Perl6では, EVALは通常は使用できないようになっており, MONKEY-SEE-NO-EVALというpragmaを実行することで使うことができるようになる.
EVALFILEはファイルパスを受け取るとファイル開き, バイト文字列に変換し読み込む,その後読み込んだバイト文字列にデコードし,ファイルパスの文字列を読み込み,ファイルの中身をEVALと同様に解釈する.
Code1の2行目にあるMONKEY−SEE−NO−EVALはRaku上でEVALFILEを使用可能にするpragmaである.


\lstinputlisting[label=codeseg,  caption=Abyssサーバーの実装のsource code]{code/abyss.p6}
\lstinputlisting[label=codeseg,  caption=クライアント側のsource code]{code/client.p6}
\lstinputlisting[label=eval,  caption=evalのサンプルコード]{code/eval.p6}
%通常、自分でプロセス立ち上げてPerl6を実行する際は,
%\section{問題点}

\section{比較}
\begin{itemize}
\item{Microsoft CLR}

.NET Framework には, 共通言語ランタイム(Common Language Runtime)と呼ばれるランタイム環境がある.
.NET対応のソフトウェアは、様々なプログラミング言語で書かれたソースコードから, いったん共通中間言語 ( Common Intermediate Language )による形式に変換されて利用者のもとに配布される.
CIL形式のプログラムを解釈し, コンピュータが直に実行可能な機械語によるプログラムに変換して実行するソフトウェアがCLRである.
現状のAbyssサーバーはprocessとして立ち上げているが, CLRはOSに直接組み込む必要があるが, Abyssサーバーはプロセス上で実行しているためOSに手を加えず実装が容易である.

\item{PyPy}

PyPy は Python の 実装の一つであり, Cpython のサブセットである RPython で記述された 処理系である.

PyPy は JIT コンパイル を採用しており, 実行時にコードを機械語にコンパイルして効率的に実行させることができる.
PyPy は Cpython より実行速度が速いが起動速度は Cpython と比較して約3倍遅い.
Perl6 と同様, PyPyは Cpython と比較して起動時間が遅いため今回提案した手法を応用できると予測できる.

\end{itemize}

\section{まとめ}
本稿では実行する Perl6 ファイル名をサーバーに転送し,コンパイラサーバーでコンパイルを行い実行することで全体的に処理時間が早くなることを示した.

今後Abyssサーバーでの開発をより深く行っていくにあたって以下のような改善点が見られた \\
\begin{itemize}

\item コンパイラの起動が遅い言語だけでなく, モジュールの読み込みが遅い言語などを, あらかじめサーバーを側でモジュールを読み込んでおき, それを利用してプログラムを実行する手法も応用できるように改良を行う.
\item 今回の実装ではTCPソケットを用いたがTCPソケットを用いるとサーバーを立ち上げた際に外部からファイルを転送される可能性があるので,Unix domain socketの実装を行い,それを用いたクライアント・サーバーを作成することで安全性が高まると考えた.
Rakuには現状Unix domainソケットの実装がないので、Unix domainソケットを実装し、自分以外が実行できないようにすることが今後の課題に挙げられる.
\item 今回用いた Perl6 の EVALFILE 自体にクライアント側に出力を返す実装追加することも今後の課題に挙げられる.
\item 現状のRakuのEVALFILEでは,出力がサーバー側に返っているので,クライアント側から出力を見るためにクライアント側に返す必要がある.
\item モジュールを送信する機能の追加
\item プログラムの実行終了したらモジュールを削除する機能の追加\\

\end{itemize}


今後の開発を行っていくにあたって, 他の Python のような script 言語にも応用できるように開発を行っていく.
\begin{thebibliography}{9}
  \bibitem{キー1} Andrew Shitov. Perl6 Deep Dive
  \bibitem{キー2} 清水隆博, 河野真治. CbC を用いた Perl6 処理系. プログラミングシンポジウム論文, 2019.
  \bibitem{キー3}  Perl6 Documentation\\({https://docs.perl6.org}) (2019/10/22 アクセス)
  \bibitem{roast}The Official Raku Test Suite \\({https://github.com/perl6/roast/})
  \bibitem{nqp}NQP - Not Quite Perl \\({https://github.com/perl6/nqp})
  \bibitem{designdoc}ThePerlFoundation: Perl 6 Design Docu- ments, ThePerlFoundation (online), available from ({https://design.raku.org})
\end{thebibliography}

\nocite{*}
\bibliographystyle{ipsjsort}
\bibliography{reference}

\end{document}