Mercurial > hg > Papers > 2017 > tatsuki-master
view slide/slide.html @ 28:222d98af3372
commit
author | tatsuki |
---|---|
date | Sun, 12 Feb 2017 18:09:55 +0900 |
parents | 796c18a4aa0d |
children | 92d6882c1143 |
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> <p>データベースには、複数のレコードをアップデートするときに、整合性を維持する仕組みとしてトランザクションがある。</p> <p>データ構造には並行処理ようにスレッドセーフなものが用意されている。しかし、複数のスレッドセーフなデータ構造はアクセスするときに整合性を維持するトランザクションは自分で用意する必要があり、標準的なものは用意されていない。</p> <p>特に複数のリストや木構造に対してトランザクションが必要になってきている。</p> </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> <div> <div> <h1>Jungleの構造とAPI</h1> <p>以下では、Jungleの構成要素と木へのアクセス方法を説明する。</p> <ol> <li>木とノード <li>トランザクション <li>名前による木の作成と取得 <li>NodePath <li>ノードの編集 <li>検索機能 </div> <h1>Jungleの構造</h1> <font size=5> <p>木は複数のノードの集合でできており、その木の集合によりJungleが構成されている。</p> <p>ノードは自身の子のリストと属性名と属性値の組でデータを持つ。これはデータベースのレコードに値する。</p> <p>通常のレコードと異なり、ノードは自身の子供を持つ。</p> <p>親から子への片方向の参照しか持たない。</p> <embed src="../figures/multiComponent.pdf" width="800" height="500"/> </font> </div> <div> <h1>JungleのTransaction</h1> <font size=5> <p>データの変更は一度生成した木を上書きせず、ルートから変更を行うノードまでコピーを行い、新しく木構造を構築する。最後にルートをアトミックに入れ替えてコミットする。コミットが失敗した場合は最初からやり直す。</p> <embed src="../figures/non_destructive_tree.pdf" width="800" height="500"/> </font> </div> <div> <h1>Jungleの木</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> <p>NodePathクラスを用いて[-1,1,2,3]を表している例を以下に貼る。</p> <embed src="../figures/nodepath.pdf" width="800" height="500"/> </font> </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>JungleTreeEditorのAPI</h1> <font size=5> <p>JungleTreeEditorが提供している木の編集APIを以下に記す。</p> <div style="padding: 10px; margin-bottom: 10px; border: 5px double #333333;"> <pre><code class="language-Java"> </code></pre> </div> </font> </div> <div> <h1>Jungleの検索機能</h1> <font size=5> <p>Jungleの木への検索は、木の走査を行うTraverserクラス内に実装してある。</p> <p>属性名key 属性値valueの組を使用して検索を行う。</p> <p>以下に検索を行う関数findの定義を記述する。</p> <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>関数findは引数に、Query query、String key、String valueの3つの引数を取り、条件に一致したノードのIteratorを返す。</p> <p>第1引数には、探索の条件を記述する関数boolean comdition(TreeNode)を定義したInterface Queryを、第2、第3引数の、String key、String valueはIndexを用いた絞込みに使用する。</p> </font> </div> <div> <h1>本修論でのJungleの改良点</h1> <font size=5> <ol> <li>高速な非破壊赤黒木の実装(O(log n)) <li>検索APIの実装(卒論時) <li>Indexの差分アップデート(O(log n)) <li>線形リストの高速化(O(1)) <li>Jungle Tree自体のバランス化による大きな木の扱い(O(log n)) </font> </div> <div> <font size=5> <h1>非破壊TreeMapによるJungleのIndex</h1> <p>Jungleは過去の版の木を全て保持している。</p> <p>過去の木に対する検索もサポートしている。</p> <p>木の版毎にIndexを持っている必要がある。</p> <p>従来は破壊的TreeMapでIndexを実現しており、木に更新が入るたびに新しいIndexをO(n)で作り直す必要があった。</p> <p>実装した非破壊TreeMapで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操作とDifferential Jungle Tree操作の実装した。</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> <embed src="../figures/PushPopDemerit.pdf" width="800" height="500"/> </font> </div> <div> <h1>Differential Jungle Tree</h1> <font size=5> <p>木のノードの追加順の線形リストが必要な場合もある。例えばLogなどである。</p> <p>Differential Jungle Treeは木の最後尾のノードへのポインタを持つ。</p> <p>最後尾に新しいノードをAtomicに書き込む。ルートは、版ごとに最後尾のノードを保持しており、 木自体は変更されるが、その版の木の長さの範囲では変更されていない。</p> <p>版ごとの最後尾を越えないようにアクセスすることで、線形木の非破壊性を維持することができる。</p> <embed src="../figures/findDifTree.pdf" width="800" height="500"/> <p></p> </font> </div> <div> <font size=6> <h1>Differential Jungle Treeの作成API</h1> <p>Differential Jungle Treeは、特別な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>差分木への追加を複数回行うと、複数回のトランザクション処理を行う必要がある。 複数の追加をSub Treeに対して破壊的に行って、そのSub Treeを差分木へ追加することにより、トランザクションを一回で済ませることができるようにしている。</p> </font> </div> <div> <font size=6> <h1>Differential Jungle Treeの編集の例</h1> <p>Differential Jungle Treeの編集例を以下の図に記す。</p> <embed src="../figures/EditDifferencialTree.pdf" width="800" height="500"/> <p></p> </font> </div> <div> <font size=6> <h1>Differential Jungle Treeの整合性</h1> <p>Default Jungle TreeへCommitは編集後の木のルートをAtomicに入れ替えることで行う。</p> <p>しかしDifferential Jungle Treeは、ルートの入れ替えと、Editorが持つ木構造の末尾ノードへのAppendの2つのプロセスからなる。</p> <p>ルートの入れ替えに関しては、Default Jungle Treeと同じように行う。</p> <p>Editorが持っている木構造の末尾ノードへのAppendは、ルートの入れ替えに成功した場合のみ行う。</p> <p>そうすることで、別Threadで行われているCommitと競合した際に、ルートを入れ替えたThreadと別ThreadがAppendを行い木の整合性が崩れることを回避している。</p> </font> </div> <div> <font size=6> <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=6> <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=6> <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=6> <h1>新たに追加した要素の評価</h1> <p>Jungleに新しく追加した機能の性能測定を行う。</p> <p>新しく実装したTreeMapとFunctionalJavaのTreeMap</p> <p>IndexのFullアップデートと差分アップデート</p> <p>Default Jungle TreeとDefferential Jungle Tree</p> <p>Default Jungle Tree と Red Black Jungle Tree</p> <p>最後に既存のDBであるPostgreSQLとMongoDBとJungleの比較を行う。</p> </font> </div> <div> <font size=6> <h1>TreeMapの測定</h1> <p>比較対象には、 TreeMap 実装前に Jungle で使用していた Functional Java の TreeMap を使用する。</p> <p> TreeMap に1000回の Get を行った際のグラフである。</p> <!-- <p>X 軸は Get を行う TreeMap のノード数。</p> <p>Y 軸は Get にかかった時間を表す。</p> --> <embed src="../result/treemap/find.pdf" width="800" height="500"/> </font> </div> <div> <font size=6> <h1>TreeMapの測定の考察</h1> <p>新たに実装したTreeMapの方が極めて高速な検索を行えている。</p> <p>理由として、JungleのTreeMapは二分探索木の探索アルゴリズムで探索するのに対して、Functional Javaは検索対象のノードがルートになる木を再構築し、ルートを返すといったアルゴリズムのを採用しているからである</p> <p>また、データのInsertは、ほぼ同じ速度、DeleteはJungleの方が極めて高速に行えていた。</p> </font> </div> <div> <font size=6> <h1>Indexの差分アップデートの測定</h1> <p>比較対象は、IndexのFullアップデートとする。</p> <p>測定は木にノードを追加、Commitを1 セットの変更として行う。</p> <!-- <p>X 軸は、木に行った変更のセット数。</p> <p>Y 軸は、木の構築にかかった時間を表す。</p> --> <embed src="../result/createIndex.pdf" width="800" height="500"/> </font> </div> <div> <font size=6> <h1>Indexの差分アップデートの測定の考察</h1> <p>IndexのFullアップデートに比べて差分Updateの方が高速に木の構築に成功している。</p> <p>期待通りの性能が出たといえる。</p> </font> </div> <div> <font size=6> <h1>正順の線形木の構築時間の測定</h1> <p>Differential Jungle Treeの性能測定を行う。</p> <p>比較対象はDefault Jungle Treeを選択した。</p> <p>また、木の構築時間を測るためにIndexを構築していない。</p> <!-- <p>X軸は構築した木のノード数。</p> <p>Y 軸は構築にかかった時間を表す。</p> --> <embed src="../result/createListTree.pdf" width="800" height="500"/> </font> </div> <div> <font size=6> <h1>正順の線形木の構築時間の考察</h1> <p>Commit毎に全てのノードの複製を行うDefault Jungle Treeに比べて、木の複製を行わないDifferential Jungle Treeが早いのは当然だといえる。</p> <p>期待通りの性能が出た。</p> </font> </div> <div> <font size=6> <h1>Red Black Jungle Tree の測定</h1> <p>比較対象は、Default Jungle Treeを選択した。</p> <embed src="../result/createRedBlackTreeAndDefaultTreeTime.pdf" width="800" height="500"/> </font> </div> <div> <font size=6> <h1>Red Black Jungle Tree の測定の考察</h1> <p>Red Black Jungle Treeは自身の木の形がIndexと同じ働きを持っている。</p> <p>なのでIndexを木の編集時作る必要がない。</p> <p>Commit のたびにIndexを作っているDefault Jungle Treeより早くなるのは当然だといえる。</p> <p>期待通りの性能が出た。</p> </font> </div> <div> <font size=6> <h1>既存のDBとJungleの比較</h1> <p>比較対象はMongoDBとPostgreSQLを選択した。</p> <p>PostgreSQLはJson形式でデータを格納している。</p> <p>データの検索速度を比較した。</p> <embed src="../result/comparedb.pdf" width="800" height="500"/> </font> </div> <div> <font size=6> <h1>既存のDBとJungleの比較の考察</h1> <p>MongoDBとPostgreSQLは、プログラム外にあるデータベースに通信を用いてアクセスしている。</p> <p>Jungleは、メモリの中にデータを持ち通信を使わずデータにアクセスできる。</p> <p>期待通りの性能が出た。</p> </font> </div> <div> <font size=6> <h1>まとめ</h1> <p>Jungleの性能を向上させるために新たな要素を追加した。</p> <ol> <li>非破壊TreeMap</li> <li>Indexの差分アップデート</li> <li>Differential Jungle Tree</li> <li>Red Black Jungle Tree</li> </ol> <p>実装後の測定では、全てが既存の木と比べて高速に動いていた。</p> <p>また、Jungleは既存のDBと比較しても、極めて高速な検索が行えることがわかった。</p> </font> </div> <div> <font size=6> <h1>今後の課題</h1> <h2>木の設計手法の確立</h2> <p>JungleはRDB と異なり格納するデータの自由度は大きい。</p> <p>どのようなデータ構造も設計を行わずに格納することが可能である。</p> <p>十分なパフォーマンスを出すためには、データを最適化する必要がある。</p> <p>最適な木構造はアプリケーションによって違うため、Jungle の設計手法を確立させる必要がある。</p> </font> </div> </div> </div> </div> <!-- presentation --> </body> </html>