Mercurial > hg > Papers > 2016 > nozomi-sigos
view paper/chapter3.tex @ 15:696a908208c8
add compress part
author | Nozomi Teruya <e125769@ie.u-ryukyu.ac.jp> |
---|---|
date | Sun, 24 May 2015 18:40:04 +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}