Mercurial > hg > Papers > 2017 > tatsuki-master
view slide/slide.html @ 35:1c2087d5f2c6
add Poster
author | tatsuki |
---|---|
date | Sun, 19 Feb 2017 03:32:55 +0900 |
parents | 5707345bb98c |
children |
line wrap: on
line source
<!DOCTYPE html> <html> <head> <meta http-equiv="content-type" content="text/html;charset=utf-8"> <title>修論予備審査Slide</title> <!-- Notes on CSS media types used: 1) projection -> slideshow mode (display one slide at-a-time; hide all others) 2) screen -> outline mode (display all slides-at-once on screen) 3) print -> print (and print preview) Note: toggle between projection/screen (that is, slideshow/outline) mode using t-key Questions, comments? - send them along to the mailinglist/forum online @ http://groups.google.com/group/webslideshow --> <!-- styles --> <style media="screen,projection"> html, body, .presentation { margin: 0; padding: 0; } .slide { display: none; position: absolute; top: 0; left: 0; margin: 0; border: none; padding: 2% 4% 0% 4%; /* css note: order is => top right bottom left */ -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; width: 100%; height: 100%; /* css note: lets use border-box; no need to add padding+border to get to 100% */ overflow-x: hidden; overflow-y: auto; z-index: 2; } .slide.current { display: block; } /* only display current slide in projection mode */ .slide .stepcurrent { color: black; } .slide .step { color: silver; } /* or hide next steps e.g. .step { visibility: hidden; } */ .slide { /* background-image: -webkit-linear-gradient(top, blue, aqua, blue, aqua); background-image: -moz-linear-gradient(top, blue, aqua, blue, aqua); */ } </style> <style media="screen"> .slide { border-top: 1px solid #888; } .slide:first-child { border: none; } </style> <style media="print"> .slide { page-break-inside: avoid; } .slide h1 { page-break-after: avoid; } .slide ul { page-break-inside: avoid; } </style> <!-- add js lib (jquery) --> <script src="js/jquery-1.7.min.js"></script> <!-- S6 JS --> <script src="js/jquery.slideshow.js"></script> <script src="js/jquery.slideshow.counter.js"></script> <script src="js/jquery.slideshow.controls.js"></script> <script> $(document).ready( function() { Slideshow.init(); // Example 2: Start Off in Outline Mode // Slideshow.init( { mode: 'outline' } ); // Example 3: Use Custom Transition // Slideshow.transition = transitionScrollUp; // Slideshow.init(); // Example 4: Start Off in Autoplay Mode with Custom Transition // Slideshow.transition = transitionScrollUp; // Slideshow.init( { mode: 'autoplay' } ); } ); </script> </head> <body> <div class="layout"> <div id="header"></div> <div id="footer"> <div align="right"> <img src="image/concurrency.png" width="200"> </div> </div> </div> <div class="presentation"> <!-- add slides here; example --> <div id="header"> <tr> <td><div align="center"> <h1><font color="#808db5">ソフトウェア内部で使用するのに適した木構造データベースJungle</font></h1> <h2>琉球大学大学院 情報工学専攻 修士2年次 金川竜己</h2> <p>Feb 13, 2017</p> </div></td> </tr> </div> <div> <h1>データベースとプログラム中のデータ構造のミスマッチ</h1> <font size=5> <p>プログラム中のデータ構造には、構造体、オブジェクトなどがある。それらが、ポインタで結合されリストや木やグラフを構成する。一部はHashMapなどに格納される。</p> <p>一方でデータベースでは、平たんな表構造を持ち、KEY属性を用いて参照する。</p> <p>例えばゲーム中のアイテムのリストは、データ構造として容易に表現されるがRDBでは、関係を表すテーブルを用いて表現する必要がある。</p> <!-- <p>データ構造の変更は、並列に行われても整合性を維持するトランザクションである必要があるが、標準的なものは提供されていない。</p> --> <p>このようにプログラム中のデータ構造とデータベースの間にはギャップがある。これをインピータンスピスマッチいうことがある。</p> </font> </div> <div> <h1>データベースのトランザクションとデータ構造のギャップ</h1> <font size=5> <p>データベースには、複数のレコードをアップデートするときに、整合性を維持する仕組みとしてトランザクションがある。</p> <p>データ構造には並行処理用にスレッドセーフなものが用意されている。</p> <p>しかし、複数のスレッドセーフなデータ構造は、アクセスするときに整合性を維持するトランザクションを自分で用意する必要があり、標準的なものは用意されていない。</p> <p>特に複数のリストや木構造に対してのトランザクションが必要になってきている。</p> </font> </div> <div> <h1>インピータンスピスマッチを乗り越えるための既存技術</h1> <font size=5> <p>これまでに開発されてきたものには、 <ol> <li>データベースのレコードをプログラム中のオブジェクトとして使えるOR Mapper <li>データベース自体も、表に特化したKey Value Store <li>Jsonなどの不定形のデータ構造をRDBのレコードとして格納する機能拡張 </ol> </p> <p>しかし、不定形の構造の変更をトランザクションとして、どのように処理するかはJsonの一括変更という形で処理されてしまっており、 並列処理が中心となってきている今のアプリケーションには向いていない。</p> <p>特に木構造自体が大きくなる場合に問題がある。</p> </font> </div> <div> <h1>非破壊的木構造データベースJungle</h1> <font size=5> <p>プログラム中のデータ構造のうち木構造やリスト構造に着目する。</p> <p>データベースJungleはこれらを直接データベースとして取り扱い、マルチスレッドからの読み書きをトランザクションとして提供する。</p> <p>Jungleの木は、外部のノードあるいはディスクに複製され、持続性を提供する。</p> <p>複数の木の間の参照などの複雑な構造はノードのKey属性のIndexを使って実現する。</p> <p>Jungleでは、データ構造の並行処理が可能なように、データの変更を非破壊的に行う。</p> <p>木が変更されている間も、その前の版を安全に読み出すことができる。</p> </font> </div> <div> <h1>Jungleによるインピータンスピスマッチの解消</h1> <font size=5> <p>Jungleはゲームなどのアイテムのリストをそのまま木構造に格納することができ、トランザクションと持続性を提供する。</p> <p>Jungleは様々な構造のデータ(例えばXML/JSON/LIST)を木構造としてそのまま格納することが可能である。</p> <p>決まった版の木は変更されないので、いちいち木を検索することなく木構造をそのままプログラムのデータ構造として用いることができる。</p> </font> </div> <div> <h1>Jungleの構造とAPI</h1> <font size=5> <p>以下では、Jungleの構成要素と木へのアクセス方法を説明する。</p> <ol> <li>木とノード <li>トランザクション <li>名前による木の作成と取得 <li>NodePath <li>ノードの編集 <li>検索機能 </ol> </font> </div> <diV> <h1>Jungleの構造</h1> <font size=5> <p>木は複数のノードの集合でできており、その木の集合によりJungleが構成されている。</p> <p>ノードは自身の子のリストと属性名と属性値の組でデータを持つ。これはデータベースのレコードに値する。</p> <p>通常のレコードと異なり、ノードは自身の子供を持つ。</p> <p>親から子への片方向の参照しか持たない。</p> <!-- <embed src="images/multiComponent.svg" width="800" height="500"/> --> </font> </div> <div> <h1>Jungleのトランザクション</h1> <font size=5> <p>データの変更は一度生成した木を上書きせず、ルートから変更を行うノードまでコピーを行い、新しく木構造を構築する。</p> <p>木の変更に関係ないノードは参照を行い過去の木と共有する。</p> <p>そして新しい木構造に変更を加える。</p> <p>最後にルートをアトミックに入れ替えてCommitする。</p> <p>他のThreadとCommitが競合し失敗した場合は最初からやり直す。</p> <!--<embed src="images/non_destructive_tree.svg" width="800" height="500"/> --> </font> </div> <div> <h1>非破壊的木構造の編集例</h1> <font size=5> <embed src="images/non_destructive_tree.svg" width="800" height="500"/> </font> </div> <div> <h1>名前による木の生成、取得</h1> <font size=5> <p>Jungleは木を名前で生成、管理している。</p> <div style="padding: 10px; margin-bottom: 10px; border: 5px double #333333;"> <pre><code class="language-Java">// Jungleに新しく木を生成する。 //木の名前が重複した場合、生成に失敗しnullを返す JungleTree createNewTree(String treeName) // JungleからtreeNameと名前が一致するtreeを取得する。 //名前が一致するTreeがない場合取得は失敗しnullを返す JungleTree getTreeByName(String treeName) </code></pre> </div> </font> </div> <div> <h1>NodePath</h1> <font size=5> <p>Jungleでは木のノードの位置をNodePathを使って表す。</p> <p>ルートから対象のノードまでの経路を数字で指し示す。</p> <p>ルートノードは例外として-1と表記される。</p> </font> </div> <div> <h1>[-1,1,2,3]を指し示す例</h1> <embed src="images/nodepath.svg" width="800" height="500"/> </div> <div> <h1>Jungleのノードの編集</h1> <font size=5> <p>Jungleのノードの編集はJungleTreeEditorを用いて行われる。</p> <p>JungleTreeEditorには編集を行うためのAPIが実装されている。</p> <p>また、ノードを指定して編集を行う際には、NodePathクラスを用いる。</p> <p>木の編集を行った後は、Commitを行い変更をPushする必要がある。</p> </font> </div> <div> <h1>Jungleの検索機能</h1> <font size=5> <p>Jungleの木への検索は、木の走査を行うInterfaceTraverserを使用して行う。</p> <p>検索はQueryインターフェースを用いる。</p> <div style="padding: 10px; margin-bottom: 10px; border: 5px double #333333;"> <pre><code class="language-Java">public interface Query { public boolean condition(TreeNode node); } </code></pre> </div> <p>Queryは、検索の条件を記述する関数conditionを持つ。</p> <p>conditionは、引数で受け取ったノードが条件に一致するならtrue返す、一致しないならfalseを返す。</p> <p>InterfaceTraverserはconditionを満たすノードを返すIteratorを返す。 </p> </font> </div> <div> <h1>Indexを使用する検索</h1> <font size=5> <div style="padding: 10px; margin-bottom: 10px; border: 5px double #333333;"> <pre><code class="language-Java">public Iterator<TreeNode> find(Query query, String key, String value); </code></pre> </div> <p>Jungleの木は全ての属性名に対してIndexを構築している。InterfaceTraverserの関数findに属性値を指定することにより、検索を高速に行うことができる。</p> <p>findは引数に、Query query、String key、String valueの3つの引数を取り、条件に一致したノードを返すIteratorを返す。</p> </font> </div> <div> <h1>本修論でのJungleの改良点</h1> <font size=5> <ol> <li>高速な非破壊赤黒木の実装(O(log n))</li><br> <li>検索APIの実装(卒論時)</li><br> <li>Indexの差分アップデート(O(log n))</li><br> <li>線形リストの高速化(O(1))</li><br> <li>Jungle Tree自体のバランス化による大きな木の扱い(O(log n))</li><br> </ol> </font> </div> <div> <font size=5> <h1>非破壊赤黒木によるJungleのIndex</h1> <p>Jungleは過去の版の木を全て保持している。</p> <p>過去の木に対する検索もサポートしている。</p> <p>木の版毎にIndexを持っている必要がある。</p> <p>従来は破壊的赤黒木でIndexを実現しており、木に更新が入るたびに新しいIndexをO(n)で作り直す必要があった。</p> <p>実装した非破壊赤黒木でIndexを実装することにより、更新をO(log n)で行うことができるようになった。 また、変更されない部分は過去の版と共有されるので、メモリ効率も改良された。 </font> </div> <!-- <div> <h1>赤黒木とは</h1> <font size=5> <p>赤黒木とは、二分探索木の一つで、以下の条件を満たした木のことである</p> <ul> <li>全てのノードは赤か黒の色を持つ</li> <li>ルートノードの色は黒</li> <li>全ての葉の色は黒</li> <li>赤いノードの子の色は黒</li> <li>全ての葉からルートまでの経路には同じ個数の黒いノードがある</li> </ul> <p>赤黒木は、上記の条件を満たしている限りデータの検索、削除、探索をO(Log n)で行える。</p> </font> </div> --> <div> <h1>線形の木の取り扱い</h1> <font size=5> <p>Jungleは木の編集時、ルートから編集を行う位置までのノードの複製を行う。</p> <p>そのため、木の編集の手間は木構造の形によって異なる。</p> <p>特に線形の木の場合、全てのノードの複製を行うため変更の手間がO(n)となってしまう。</p> <p>線形の木をO(1)で変更するPush/Pop操作と差分木操作の実装した。</p> </font> </div> <div> <h1>Push/Pop</h1> <font size=5> <p>線形リストのルートの上にルートを付け加える操作(Push)はO(1)である。</p> <p>逆にルートを取り除き、その子供をルートにする操作(Pop)もO(1)である。</p> <p>これらにより、線形木を高速に操作することができる。</p> <p>Pushを連続で行うと、リストは逆順に構築される。</p> </font> </div> <div> <h1>Push/Pop</h1> <embed src="images/PushPopDemerit.svg" width="800" height="500"/> </font> </div> <div> <h1>差分木</h1> <font size=5> <p>木のノードの追加順の線形リストが必要な場合もある。例えばLogなどである。</p> <p>差分木は木の最後尾のノードへのポインタを持つ。</p> <p>最後尾に新しいノードをAtomicに書き込む。</p> <p>ルートは版ごとに最後尾のノードを保持しており、 木自体は変更されるが、その版の木の長さの範囲では変更されていない。</p> <p>版ごとの最後尾を越えないようにアクセスすることで、線形木の非破壊性を維持することができる。</p> <p></p> </font> </div> <div> <h1>差分木</h1> <font size=5> <embed src="images/findDifTree.svg" width="800" height="500"/> <p></p> </font> </div> <div> <font size=5> <h1>差分木の作成API</h1> <p>差分木は、特別なAPIで作成する必要がある。</p> <div style="padding: 10px; margin-bottom: 10px; border: 5px double #333333;"> <pre><code class="language-Java"> JungleTree createNewDifferenceTree(String treeName); </code></pre> </div> <p>createNewDifferenceTreeは、第一引数で指定した名前の差分木を構築する。</p> <p>差分木の取得に関しては既存の木と同じように行える。</p> <p>既存の木、差分木ともにJungleTreeInterfaceを実装しているからである。</p> </font> </div> <div> <font size=5> <h1>差分木の編集</h1> <p>差分木へノードの追加を複数回行うと、複数回のトランザクション処理を行う必要がある。</p> </p>複数の追加をSub Treeに対して破壊的に行って、そのSub Treeを差分木へ追加することにより、トランザクションを一回で済ませることができるようにしている。</p> </font> </div> <div> <font size=5> <h1>差分木の編集の例</h1> <embed src="images/EditDifferencialTree.svg" width="800" height="450"/> <p></p> </font> </div> <div> <font size=5> <h1>差分木の整合性</h1> <p>既存のJungleTreeへのCommitは編集後の木のルートをAtomicに入れ替えることで行う。</p> <p>しかし差分木は、ルートの入れ替えと、Sub Treeの末尾ノードへのAppendの2つのプロセスからなる。</p> <p>ルートの入れ替えに関しては、既存のJungle Treeと同じように行う。</p> <p>Sub Treeの末尾ノードへのAppendは、ルートの入れ替えに成功した場合のみ行う。</p> <p>そうすることで、別Threadで行われているCommitと競合した際に、ルートを入れ替えたThreadと別ThreadがAppendを行い木の整合性が崩れることを回避している。</p> </font> </div> <div> <font size=5> <h1>Jungle上での巨大な木の扱い</h1> <p>Jungleは木の編集時、ルートから編集を行う位置までのノードの複製を行う。</p> <p>そのため、木の編集の手間は木構造の大きさにも依存している。</p> <p>バランスの取れた木構造を構築することで、編集の手間をO(log n)にすることは可能ではある。</p> <p>しかし、ユーザーが木の構造を把握しバランスを取るのは難しい。</p> <p>そこで、自動で木のバランスを取り、最適な木構造を構築する機能を持つRed Black Jungle Treeを実装した。</p> <p>Red Black Jungle Treeは、木構造を指定した作成を行うことはできないが、Key属性を用いて任意のノードにアクセスすることができる。</p> </font> </div> <div> <font size=5> <h1>Red Black Jungle Treeの作成API</h1> <p>Red Black Jungle Treeは、特別なAPIで作成する必要がある。</p> <div style="padding: 10px; margin-bottom: 10px; border: 5px double #333333;"> <pre><code class="language-Java"> JungleTree createNewRedBlackTree(String treeName,String balanceKey); </code></pre> </div> <p>上記のAPIは、treeNameで指定した名前のRed Black Jungle Treeを構築する。</p> <p>また、第二引数のbalanceKeyを用いて木のバランスを取る。</p> </font> </div> <div> <font size=5> <h1>NodePathの拡張</h1> <p>Red Black Jungle Treeは、ノードを追加、削除するたびに木のバランスが行われるため、各ノードのPathが変わってしまう。</p> <p>その為、編集を加える際に、編集対象のノードのPathを調べる必要がある。</p> <p>その問題を解決するために、ノードを数値ではなく属性名と属性値の組でノードを指定できるようにした。</p> <p>ノードの指定に使用する属性名は、Red Black Jungle Treeの第二引数で指定したbalanceKeyを使用する必要がある。</p> </font> </div> <div> <font size=5> <h1>Jungleの評価</h1> <ol> <li>測定対象はPostgreSQLとMongoDBとJungle</li> <li>データベースに対する10000回の検索速度の比較を行う。</li><br> <li>Json形式で100人分のデータを格納する。</li><br> <li>1人あたりのデータの大きさを変更する。</li> </ol> <p></p> </font> </div> <div> <font size=4> <p>グラフのX軸は、データ1件あたりのJSONのサイズ。</p> <p>グラフのY軸は、検索にかかった時間を表している。</p> <embed src="images/compareDBbigJson.svg" width="700" height="460"/> </font> </div> <div> <h1>既存のDBとの比較2</h1> <font size=4> <p>次はJsonのサイズではなく、格納するデータ量を変更する。</p> <p>1人分のデータサイズは2304biteとする。</p> </font> </div> <div> <font size=4> <p>グラフのX軸は、データ1件あたりのJSONのサイズ。</p> <p>グラフのY軸は、検索にかかった時間を表している。</p> <embed src="images/compareDBPersonJson.svg" width="700" height="460"/> </font> </div> <div> <font size=5> <h1>既存のDBとJungleの比較の考察</h1> <p>PostgreSQLは、JSONのサイズが大きくなると性能が落ちる。一方、MongoDBとJungleはJSONのサイズが変わっても性能はあまり落ちない。</p> <p>一方格納するデータ数が増えても、検索にかかる時間はそこまで変わっていない。</p> <p>PostgreSQLのIndexは、JSONのサイズには対応していなかった。</p> <p>MongoDBとJungleの性能差の理由としては、通信の有無が原因と考えられる。</p> <p>MongoDBは通信を介してデータにアクセスしているのに対して、Jungleはプログラムの中にデータを持つため通信を行わずにデータにアクセスできている。</p> </font> </div> <div> <font size=4> <h1>まとめ</h1> <p>Jungleの性能を向上させるために新たな要素を追加した。</p> <ol> <li>高速な非破壊赤黒木の実装</li><br> <li>検索APIの実装</li><br> <li>Indexの差分アップデート)</li><br> <li>線形リストの高速化</li><br> <li>Jungle Tree自体のバランス化による大きな木の扱い</li><br> </ol> <p>Jungleは既存のDBと比較しても、極めて高速な検索が行えることがわかった。</p> </font> </div> <div> <font size=5> <h1>今後の課題</h1> <h2>木の設計手法の確立</h2> <p>JungleはRDB と異なり格納するデータの自由度は大きい。</p> <p>どのようなデータ構造も設計を行わずに格納することが可能である。</p> <p>十分なパフォーマンスを出すためには、データを最適化する必要がある。</p> <p>最適な木構造はアプリケーションによって違うため、Jungle の設計手法を確立させる必要がある。</p> </font> </div> <div> <font size=5> <h1>発表履歴</h1> <ol> <li>非破壊的木構造データベースJungleとその評価, 金川竜己 , 河野真治 (琉球大学)<br> システムソフトウェアとオペレーティング・システム研究会 ,2015 Okinawa, May, 2015</li><br> <li>ソフトウェア内部で使用するのに適した木構造データベースJungle<br> 金川竜己, 武田和馬(琉球大学), 河野真治(琉球大学),第58回プログラミング・シンポジウム, Jan, 2017</li><br> </ol> </font> </div> <div> <font size=5> <h1>付録</h1> <p>実装した機能の測定を以降に記述する。</p> </font> </div> <div> <font size=5> <h1>TreeMapの測定</h1> <p>比較対象には、 TreeMap 実装前に Jungle で使用していた Functional Java の TreeMap を使用する。</p> <p> TreeMap に1000回の Get を行った際のグラフである。</p> </font> </div> <div> <font size=5> <p>X 軸は Get を行う TreeMap のノード数。</p> <p>Y 軸は Get にかかった時間を表す。</p> <embed src="images/find.svg" width="700" height="460"/> </font> </div> <div> <font size=5> <h1>Indexの差分アップデートの測定</h1> <p>比較対象は、IndexのFullアップデートとする。</p> <p>測定は木にノードを追加、Commitを1 セットの変更として行う。</p> </font> </div> <div> <font size=5> <p>X 軸は、木に行った変更のセット数。</p> <p>Y 軸は、木の構築にかかった時間を表す。</p> <embed src="images/createIndex.svg" width="700" height="460"/> </font> </div> <div> <font size=5> <h1>正順の線形木の構築時間の測定</h1> <p>Differential Jungle Treeの性能測定を行う。</p> <p>比較対象はDefault Jungle Treeを選択した。</p> <p>また、木の構築時間を測るためにIndexを構築していない。</p> </font> </div> <div> <font size=5> <p>X軸は構築した木のノード数。</p> <p>Y軸は構築にかかった時間を表す。</p> <embed src="images/createListTree.svg" width="700" height="460"/> </font> </div> <div> <font size=5> <h1>Red Black Jungle Tree の測定</h1> <p>比較対象は、Default Jungle Treeを選択した。</p> </font> </div> <div> <font size=5> <p>X軸は構築した木のノード数。</p> <p>Y軸は構築にかかった時間を表す。</p> <embed src="images/createRedBlackTreeAndDefaultTreeTime.svg" width="800" height="500"/> </font> </div> </div> </div> </div> <!-- presentation --> </body> </html>