# HG changeset patch # User tatsuki # Date 1486893336 -32400 # Node ID 92d6882c114390cdb4ae8e45c3b56db5ee0ba4f0 # Parent 222d98af3372e177e81b2de559283c39cf5a12c6 add svg diff -r 222d98af3372 -r 92d6882c1143 slide/images/EditDifferencialTree.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/slide/images/EditDifferencialTree.svg Sun Feb 12 18:55:36 2017 +0900 @@ -0,0 +1,610 @@ + +image/svg+xml1 +0 +(root) + + + +Tree +ver1 +5 +(subTree +Root) +Editor +2. addNewChild +(<-1,0>) +5 +(subTree +Root) +Editor +6 +3. commit +1 +0 +(root) + + + +Tree +ver2 +5 +(subTree +Root) +6 +保持 +保持 +1. getJungle +TreeEditor() + \ No newline at end of file diff -r 222d98af3372 -r 92d6882c1143 slide/images/PushPopDemerit.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/slide/images/PushPopDemerit.svg Sun Feb 12 18:55:36 2017 +0900 @@ -0,0 +1,305 @@ + +image/svg+xml0 +(root) +0 +1 +(root) +0 +1 +2 +(root) +0 +1 +2 +3 +(root) + \ No newline at end of file diff -r 222d98af3372 -r 92d6882c1143 slide/images/comparedb.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/slide/images/comparedb.svg Sun Feb 12 18:55:36 2017 +0900 @@ -0,0 +1,262 @@ + +image/svg+xml-500 +0 +500 +1000 +1500 +2000 +2500 +3000 +1000 +2000 +3000 +4000 +5000 +6000 +7000 +8000 +9000 +10000 +time(ms) +nodeCount +"jungleFindBenchMark" using 1:2 +"mongFindBenchMark" using 1:2 +"postgresFindBenchMark" using 1:2 + \ No newline at end of file diff -r 222d98af3372 -r 92d6882c1143 slide/images/createIndex.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/slide/images/createIndex.svg Sun Feb 12 18:55:36 2017 +0900 @@ -0,0 +1,275 @@ + +image/svg+xml0 +100 +200 +300 +400 +500 +600 +0 +200 +400 +600 +800 +1000 +time(m) +NodeCount +"createIndexFullUpdate" using 1:2 +"createIndexDifferenceUpdate" using 1:2 + \ No newline at end of file diff -r 222d98af3372 -r 92d6882c1143 slide/images/createListTree.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/slide/images/createListTree.svg Sun Feb 12 18:55:36 2017 +0900 @@ -0,0 +1,275 @@ + +image/svg+xml0 +50 +100 +150 +200 +250 +0 +50 +100 +150 +200 +250 +300 +time(m) +NodeCount +"defaultJungleListTreeCreateTime" using 1:2 +"differentialListTreeCreateTime" using 1:2 + \ No newline at end of file diff -r 222d98af3372 -r 92d6882c1143 slide/images/createRedBlackTreeAndDefaultTreeTime.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/slide/images/createRedBlackTreeAndDefaultTreeTime.svg Sun Feb 12 18:55:36 2017 +0900 @@ -0,0 +1,212 @@ + +image/svg+xml0 +5 +10 +15 +20 +25 +30 +35 +0 +200 +400 +600 +800 +1000 +time(ms) +nodeCount +"defaultJungleTreeCreateTime" using 1:2 +"redBlackTreeCreateTime" using 1:2 + \ No newline at end of file diff -r 222d98af3372 -r 92d6882c1143 slide/images/find.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/slide/images/find.svg Sun Feb 12 18:55:36 2017 +0900 @@ -0,0 +1,222 @@ + +image/svg+xml0 +500 +1000 +1500 +2000 +100 +200 +300 +400 +500 +600 +700 +800 +900 +1000 +time(ms) +NodeCount +"functionalJavaTreeMapFind" using 1:2 +"jungleTreMapFind" using 1:2 + \ No newline at end of file diff -r 222d98af3372 -r 92d6882c1143 slide/images/findDifTree.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/slide/images/findDifTree.svg Sun Feb 12 18:55:36 2017 +0900 @@ -0,0 +1,426 @@ + +image/svg+xml1 +0 +(root) + +(末尾 +ノード) +Tree +ver1 +1 +0 +(root) + +Tree +ver2 +3 +(subTree +Root) +4 +(末尾 +ノード) +保持 +保持 +3 +(subTree +Root) +4 + \ No newline at end of file diff -r 222d98af3372 -r 92d6882c1143 slide/images/findTime.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/slide/images/findTime.svg Sun Feb 12 18:55:36 2017 +0900 @@ -0,0 +1,242 @@ + +image/svg+xml0 +5000 +10000 +15000 +20000 +25000 +10000 +20000 +30000 +40000 +50000 +60000 +70000 +80000 +90000 +100000 +time(ms) +FindCount +"postgresFindBenchMark" using 1:2 +"mongFindBenchMark" using 1:2 +"jungleFindBenchMark" using 1:2 + \ No newline at end of file diff -r 222d98af3372 -r 92d6882c1143 slide/images/multiComponent.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/slide/images/multiComponent.svg Sun Feb 12 18:55:36 2017 +0900 @@ -0,0 +1,217 @@ + +image/svg+xmldisplayComponentName : +diaryImage@Component +Node2 +Node3 +Node4 +displayComponentName : +diaryText@Component +NodeName : +Multi@Component +Node1 +NodeName : +displayinfomation + \ No newline at end of file diff -r 222d98af3372 -r 92d6882c1143 slide/images/nodepath.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/slide/images/nodepath.svg Sun Feb 12 18:55:36 2017 +0900 @@ -0,0 +1,371 @@ + +image/svg+xmlroot +-1 +0 +1 +... +n +0 +1 +2 +3 +0 +1 +2 +3 +編集対象 +NodePath<-1,1,2,3> +tree_name + \ No newline at end of file diff -r 222d98af3372 -r 92d6882c1143 slide/images/non_destructive_tree.svg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/slide/images/non_destructive_tree.svg Sun Feb 12 18:55:36 2017 +0900 @@ -0,0 +1,795 @@ + +image/svg+xmlroot から変更の +あったノードま +でコピーを行う +root +1 +2 +3 +4 +5 +root +1 +2 +3 +4 +5 +root +2 +100 + \ No newline at end of file diff -r 222d98af3372 -r 92d6882c1143 slide/slide.html --- a/slide/slide.html Sun Feb 12 18:09:55 2017 +0900 +++ b/slide/slide.html Sun Feb 12 18:55:36 2017 +0900 @@ -125,9 +125,11 @@

データベースのトランザクションとデータ構造のギャップ

+

データベースには、複数のレコードをアップデートするときに、整合性を維持する仕組みとしてトランザクションがある。

データ構造には並行処理ようにスレッドセーフなものが用意されている。しかし、複数のスレッドセーフなデータ構造はアクセスするときに整合性を維持するトランザクションは自分で用意する必要があり、標準的なものは用意されていない。

特に複数のリストや木構造に対してトランザクションが必要になってきている。

+
@@ -168,10 +170,12 @@

Jungleはゲームなどのアイテムのリストをそのまま木構造に格納することができ、トランザクションと持続性を提供する。

Jungleは様々な構造のデータ(例えばXML/JSON/LIST)を木構造としてそのまま格納することが可能である。

決まった版の木は変更されないので、いちいち木を検索することなく木構造をそのままプログラムのデータ構造として用いることができる。

-
+ +

Jungleの構造とAPI

+

以下では、Jungleの構成要素と木へのアクセス方法を説明する。

  1. 木とノード @@ -180,23 +184,28 @@
  2. NodePath
  3. ノードの編集
  4. 検索機能 +
+
+

Jungleの構造

木は複数のノードの集合でできており、その木の集合によりJungleが構成されている。

ノードは自身の子のリストと属性名と属性値の組でデータを持つ。これはデータベースのレコードに値する。

通常のレコードと異なり、ノードは自身の子供を持つ。

親から子への片方向の参照しか持たない。

- +

JungleのTransaction

-

データの変更は一度生成した木を上書きせず、ルートから変更を行うノードまでコピーを行い、新しく木構造を構築する。最後にルートをアトミックに入れ替えてコミットする。コミットが失敗した場合は最初からやり直す。

- +

データの変更は一度生成した木を上書きせず、ルートから変更を行うノードまでコピーを行い、新しく木構造を構築する。

+<[>最後にルートをアトミックに入れ替えてCommitする。

+

他のThreadとCommitが競合し失敗した場合は最初からやり直す。

+
@@ -226,8 +235,8 @@

Jungleでは木のノードの位置をNodePathを使って表す。

ルートから対象のノードまでの経路を数字で指し示す。

ルートノードは例外として-1と表記される。

-

NodePathクラスを用いて[-1,1,2,3]を表している例を以下に貼る。

- +

NodePathクラスを用いて[-1,1,2,3]を表している例を以下に記述する。

+ @@ -247,23 +256,6 @@ - - -
-

JungleTreeEditorのAPI

- -

JungleTreeEditorが提供している木の編集APIを以下に記す。

-
-

-
-
-
- -
-
- - -

Jungleの検索機能

@@ -290,11 +282,12 @@

本修論でのJungleの改良点

    -
  1. 高速な非破壊赤黒木の実装(O(log n)) -
  2. 検索APIの実装(卒論時) -
  3. Indexの差分アップデート(O(log n)) -
  4. 線形リストの高速化(O(1)) -
  5. Jungle Tree自体のバランス化による大きな木の扱い(O(log n)) +
  6. 高速な非破壊赤黒木の実装(O(log n))

  7. +
  8. 検索APIの実装(卒論時)

  9. +
  10. Indexの差分アップデート(O(log n))

  11. +
  12. 線形リストの高速化(O(1))

  13. +
  14. Jungle Tree自体のバランス化による大きな木の扱い(O(log n))

  15. +
@@ -347,50 +340,51 @@

逆にルートを取り除き、その子供をルートにする操作(Pop)もO(1)である。

これらにより、線形木を高速に操作することができる。

Pushを連続で行うと、リストは逆順に構築される。

- +
-

Differential Jungle Tree

+

差分木

木のノードの追加順の線形リストが必要な場合もある。例えばLogなどである。

-

Differential Jungle Treeは木の最後尾のノードへのポインタを持つ。

-

最後尾に新しいノードをAtomicに書き込む。ルートは、版ごとに最後尾のノードを保持しており、 +

差分木は木の最後尾のノードへのポインタを持つ。

+

最後尾に新しいノードをAtomicに書き込む。ルートは版ごとに最後尾のノードを保持しており、 木自体は変更されるが、その版の木の長さの範囲では変更されていない。

版ごとの最後尾を越えないようにアクセスすることで、線形木の非破壊性を維持することができる。

- +

- -

Differential Jungle Treeの作成API

-

Differential Jungle Treeは、特別なAPIで作成する必要がある。

+ +

差分木の作成API

+

差分木は、特別なAPIで作成する必要がある。

 JungleTree createNewDifferenceTree(String treeName);
 
-

差分木への追加を複数回行うと、複数回のトランザクション処理を行う必要がある。 -複数の追加をSub Treeに対して破壊的に行って、そのSub Treeを差分木へ追加することにより、トランザクションを一回で済ませることができるようにしている。

+

差分木への追加を複数回行うと、複数回のトランザクション処理を行う必要がある。

+ +

複数の追加をSub Treeに対して破壊的に行って、そのSub Treeを差分木へ追加することにより、トランザクションを一回で済ませることができるようにしている。

- +

Differential Jungle Treeの編集の例

Differential Jungle Treeの編集例を以下の図に記す。

- +

- +

Differential Jungle Treeの整合性

Default Jungle TreeへCommitは編集後の木のルートをAtomicに入れ替えることで行う。

しかしDifferential Jungle Treeは、ルートの入れ替えと、Editorが持つ木構造の末尾ノードへのAppendの2つのプロセスからなる。

@@ -402,7 +396,7 @@
- +

Jungle上での巨大な木の扱い

Jungleは木の編集時、ルートから編集を行う位置までのノードの複製を行う。

そのため、木の編集の手間は木構造の大きさにも依存している。

@@ -414,7 +408,7 @@
- +

Red Black Jungle Treeの作成API

Red Black Jungle Treeは、特別なAPIで作成する必要がある。

@@ -428,7 +422,7 @@
- +

NodePathの拡張

Red Black Jungle Treeは、ノードを追加、削除するたびに木のバランスが行われるため、各ノードのPathが変わってしまう。

その為、編集を加える際に、編集対象のノードのPathを調べる必要がある。

@@ -439,21 +433,23 @@
- +

新たに追加した要素の評価

-

Jungleに新しく追加した機能の性能測定を行う。

-

新しく実装したTreeMapとFunctionalJavaのTreeMap

-

IndexのFullアップデートと差分アップデート

-

Default Jungle TreeとDefferential Jungle Tree

-

Default Jungle Tree と Red Black Jungle Tree

-

最後に既存のDBであるPostgreSQLとMongoDBとJungleの比較を行う。

+
    +
  1. Jungleに新しく追加した機能の性能測定を行う。

  2. +
  3. 新しく実装したTreeMapとFunctionalJavaのTreeMap

  4. +
  5. IndexのFullアップデートと差分アップデート

  6. +
  7. Default Jungle TreeとDefferential Jungle Tree

  8. +
  9. Default Jungle Tree と Red Black Jungle Tree

  10. +
  11. 最後に既存のDBであるPostgreSQLとMongoDBとJungleの比較を行う。

  12. +
- +

TreeMapの測定

比較対象には、 TreeMap 実装前に Jungle で使用していた Functional Java の TreeMap を使用する。

TreeMap に1000回の Get を行った際のグラフである。

@@ -461,14 +457,14 @@

X 軸は Get を行う TreeMap のノード数。

Y 軸は Get にかかった時間を表す。

--> - +
- +

TreeMapの測定の考察

新たに実装したTreeMapの方が極めて高速な検索を行えている。

理由として、JungleのTreeMapは二分探索木の探索アルゴリズムで探索するのに対して、Functional Javaは検索対象のノードがルートになる木を再構築し、ルートを返すといったアルゴリズムのを採用しているからである

@@ -477,7 +473,7 @@
- +

Indexの差分アップデートの測定

比較対象は、IndexのFullアップデートとする。

測定は木にノードを追加、Commitを1 セットの変更として行う。

@@ -485,12 +481,12 @@

X 軸は、木に行った変更のセット数。

Y 軸は、木の構築にかかった時間を表す。

--> - +
- +

Indexの差分アップデートの測定の考察

IndexのFullアップデートに比べて差分Updateの方が高速に木の構築に成功している。

期待通りの性能が出たといえる。

@@ -498,7 +494,7 @@
- +

正順の線形木の構築時間の測定

Differential Jungle Treeの性能測定を行う。

比較対象はDefault Jungle Treeを選択した。

@@ -507,12 +503,12 @@

X軸は構築した木のノード数。

Y 軸は構築にかかった時間を表す。

--> - +
- +

正順の線形木の構築時間の考察

Commit毎に全てのノードの複製を行うDefault Jungle Treeに比べて、木の複製を行わないDifferential Jungle Treeが早いのは当然だといえる。

期待通りの性能が出た。

@@ -520,35 +516,34 @@
- +

Red Black Jungle Tree の測定

比較対象は、Default Jungle Treeを選択した。

- +
- +

Red Black Jungle Tree の測定の考察

Red Black Jungle Treeは自身の木の形がIndexと同じ働きを持っている。

-

なのでIndexを木の編集時作る必要がない。

Commit のたびにIndexを作っているDefault Jungle Treeより早くなるのは当然だといえる。

期待通りの性能が出た。

- +

既存のDBとJungleの比較

比較対象はMongoDBとPostgreSQLを選択した。

PostgreSQLはJson形式でデータを格納している。

データの検索速度を比較した。

- +
- +

既存のDBとJungleの比較の考察

MongoDBとPostgreSQLは、プログラム外にあるデータベースに通信を用いてアクセスしている。

Jungleは、メモリの中にデータを持ち通信を使わずデータにアクセスできる。

@@ -559,14 +554,15 @@
- +

まとめ

Jungleの性能を向上させるために新たな要素を追加した。

    -
  1. 非破壊TreeMap
  2. -
  3. Indexの差分アップデート
  4. -
  5. Differential Jungle Tree
  6. -
  7. Red Black Jungle Tree
  8. +
  9. 高速な非破壊赤黒木の実装(O(log n))

  10. +
  11. 検索APIの実装(卒論時)

  12. +
  13. Indexの差分アップデート(O(log n))

  14. +
  15. 線形リストの高速化(O(1))

  16. +
  17. Jungle Tree自体のバランス化による大きな木の扱い(O(log n))

実装後の測定では、全てが既存の木と比べて高速に動いていた。

また、Jungleは既存のDBと比較しても、極めて高速な検索が行えることがわかった。

@@ -575,7 +571,7 @@
- +

今後の課題

木の設計手法の確立

JungleはRDB と異なり格納するデータの自由度は大きい。

@@ -586,6 +582,16 @@
+
+ +

発表履歴

+
    +
  1. 非破壊的木構造データベースJungleとその評価, 金川竜己 , 河野真治 (琉球大学)
    システムソフトウェアとオペレーティング・システム研究会 ,2015 Okinawa, May, 2015

  2. +
  3. ソフトウェア内部で使用するのに適した木構造データベースJungle
    金川竜己, 武田和馬(琉球大学), 河野真治(琉球大学),第58回プログラミング・シンポジウム, Jan, 2017

  4. +
+
+
+