view paper/chapter3.tex @ 23:7de82f13512b default tip

last update
author Nozomi Teruya <e125769@ie.u-ryukyu.ac.jp>
date Wed, 08 Jul 2015 17:34:13 +0900
parents 4a7fa91ef60a
children
line wrap: on
line source

\section{Aliceの新機能}
実用的なアプリケーションであるTreeVNCをAlice上で実装することで、Aliceに必要な機能を洗い出した。
\subsection{flip機能}
Data Segment APIのput、updateを呼ぶとOutput Data Segmentが毎回新しく作成される。そして出力するデータのコピーが行われる。
しかし、AliceVNCのようにInput Data Segmentとして取得したデータをそのまま子ノードにOutput Data Segmentとして出力する場合、コピーを行なうのは無駄である。
 
そこで、このコピーを無くしData Segmentの更新におけるオーバーヘッドを減らす方法としてflip機能の実装を行った。
ソースコード\ref{src:exampleFlip}のようにInput Data SegmentであるReceiverをflipメソッドに引数として渡すことで、無駄なコピーを減らす。
\begin{table}[html]
\lstinputlisting[label=src:flipAlice, caption=Aliceにおけるflip]{source/flip.java}
\end{table}

\begin{table}[html]
\lstinputlisting[label=src:exampleFlip,caption=flipの使用例]{source/Sort.java}
\end{table}

\subsection{Data Segmentの表現の追加(圧縮機能)}
TreeVNCでは画面配信の際、データを圧縮してノード間通信を行っている。
そのため、AliceVNCにも圧縮されたデータ形式を扱える機能が必要だと考えた。
しかし、ただデータを圧縮する機構を追加すればいいわけではない。

AliceVNCでは、ノードは受け取った画面データを描画すると同時に、子ノードのRemote DS Managerに送信する。
ノードはDSを受信するとそれを一度解凍して画面を表示し、再圧縮して子ノードに送信する。
しかし、受け取ったデータを自分の子ノードに対して送信する際には、解凍する必要はない。
圧縮状態のまま子ノードに送信ができれば、解凍・再圧縮するオーバーヘッドを無くすことができる。

そこで、1つのData Segmentに対し複数の表現を持たせることで、必要に応じた形式でDSを扱うことを可能にした。
DSを扱うReceiveData.classに、次の3種類の表現を同時に持つことができる。

\begin{enumerate}
  \item 一般的なJavaのクラスオブジェクト
  \item MessagePack for Javaでシリアライズ化されたバイナリオブジェクト
  \item 2を圧縮したバイナリオブジェクト
\end{enumerate}

ソースコード\ref {src:ReceiveData}はReceiveData.classが持つ表現であり、{\tt val}に1. 一般的なJavaのクラスオブジェクト の表現でデータ本体が保存される。{\tt messagePack}には2. シリアライズ化されたバイナリオブジェクトが保存され、通常のRemoteDSMへの通信にこの表現が扱われる。そして、{\tt zMessagePack}には3. 圧縮されたバイナリオブジェクトが保存される。
\begin{table}[html]
\lstinputlisting[label=src:ReceiveData, caption=データを表現するクラス]{source/ReceiveData.java}
\end{table}

また、圧縮状態を持つDSを扱うDSMとしてLocalとRemoteそれぞれにCompressed Data Segment Managerの追加した。
put/updateでは、ソースコード\ref{src:zput}のように指定するDSM名の先頭に"compressed"をつけることでDSは自動で圧縮状態も持つようになる。さらに、take/peekもソースコード\ref{src:ztake}のようにsetKeyを実行する際にDSM名の先頭に"compressed"をつけることで圧縮形式でDSを受け取ることができる。
\begin{table}[html]
\lstinputlisting[label=src:zput, caption=圧縮DSのput]{source/compress_put.java}
\end{table}

\begin{table}[html]
\lstinputlisting[label=src:ztake,caption=圧縮DSのtake]{source/compress_take.java}
\end{table}

これによりユーザは指定するDSMを変えるだけで、他の計算部分を変えずに圧縮表現を持つDSを扱うことができる。

ノードは圧縮されたDSを受け取った後、そのまま子ノードにflipすれば圧縮状態のまま送信されるので、送信の際の再圧縮がなくなる。
また、画面表示の際は{\tt asClass()}(ソースコード\ref {src:asClass})を使うことで適切な形式でデータを取得できる。
{\tt asClass()}はDSを目的の型にcastするメソッドであり、圧縮されていれば解凍してcastを行っている。
これにより必要なDSを必要な時にだけ解凍できる。

\begin{table}[html]
\lstinputlisting[label=src:asClass, caption=asClassの処理]{source/asClass.java}
\end{table}

\subsection{パケットの再設計}
2.4で述べたように、Remoteからputされたデータは必ずシリアライズ化されておりbyteArrayで表現される。
しかし、putされたbyteArrayが全てシリアライズ化された状態であるとはいえない。Localからも一般的なJavaのクラスオブジェクトとしてbyteArrayが使用されている場合が存在する。例えば、AliceVNCで使われる画像データはbyteArrayで表現されているが、これはLocalからputされている。
また、データの表現に圧縮形式を追加したことで、RemoteからでもputされたbyteArrayが圧縮されているのかそうでないのかが判断できなくなった。

ここからわかることは、データを表現するにはデータ単体をやりとりするだけでは不十分ということである。
そこで、データとデータの状態を表すヘッダをまとめて1つのオブジェクトとして扱うように変更した。
Aliceの通信におけるヘッダにあたるCommandMessage.class(ソースコード\ref {src:CommandMessage}にシリアライズ状態表すフラグと、圧縮状態を表すフラグを追加した。
これによってputされたDSMはフラグに応じた適切な形式でReceiveData.class内にDSを格納できる。
また、CommandMessage.classに圧縮前のデータサイズも追加したことで、適切な解凍が可能になった。

\begin{table}[html]
\lstinputlisting[label=src:CommandMessage, caption=変更後のCommandMessage]{source/CommandMessage.java}
\end{table}

\begin{table}[htbp]
\caption{CommandMessageの変数名の説明}
\label{tb:variable}
\begin{center}
\begin{tabular} {|l|l|}
  \hline
  変数名&説明\\
  \hline
  type&CommandType {\tt PEEK, PUT}などを表す\\
  \hline
  seq&Data Segmentの待ち合わせを行っている\\Code Segmentを表すunique number\\
  \hline
  key&どのKeyに対して操作を行うか指定する\\
  \hline

  quickFlag&SEDAを挟まずCommandを処理を行うかを示す\\
  \hline
  serialized&データ本体のシリアライズ状態を示す\\
  \hline

  compressed&データ本体のシリアライズ状態を示す\\
  \hline

  dataSize&圧縮前のデータサイズを表す\\
  \hline

\end{tabular}
\end{center}
\end{table}