提交 2d531580 authored 作者: Thomas Mueller's avatar Thomas Mueller

A persistent multi-version map (work in progress): r-tree

上级 ecf54428
......@@ -7,6 +7,7 @@
package org.h2.test.store;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import org.h2.dev.store.btree.DataType;
import org.h2.dev.store.btree.DataUtils;
......@@ -126,10 +127,15 @@ public class SpatialType implements DataType {
public float getAreaIncrease(Object objA, Object objB) {
SpatialKey a = (SpatialKey) objA;
SpatialKey b = (SpatialKey) objB;
float areaOld = 1, areaNew = 1;
for (int i = 0; i < dimensions; i++) {
float min = a.min(i);
float max = a.max(i);
float min = a.min(0);
float max = a.max(0);
float areaOld = max - min;
min = Math.min(min, b.min(0));
max = Math.max(max, b.max(0));
float areaNew = max - min;
for (int i = 1; i < dimensions; i++) {
min = a.min(i);
max = a.max(i);
areaOld *= max - min;
min = Math.min(min, b.min(i));
max = Math.max(max, b.max(i));
......@@ -197,4 +203,65 @@ public class SpatialType implements DataType {
return new SpatialKey(0, minMax);
}
/**
* Get the most extreme pair (elements that are as far apart as possible).
* This method is used to split a page (linear split). If no extreme objects
* could be found, this method returns null.
*
* @param list the objects
* @return the indexes of the extremes
*/
public int[] getExtremes(ArrayList<Object> list) {
SpatialKey bounds = (SpatialKey) createBoundingBox(list.get(0));
SpatialKey boundsInner = (SpatialKey) createBoundingBox(bounds);
for (int i = 0; i < dimensions; i++) {
float t = boundsInner.min(i);
boundsInner.setMin(i, boundsInner.max(i));
boundsInner.setMax(i, t);
}
for (int i = 0; i < list.size(); i++) {
Object o = list.get(i);
increaseBounds(bounds, o);
increaseMaxInnerBounds(boundsInner, o);
}
double best = 0;
int bestDim = 0;
for (int i = 0; i < dimensions; i++) {
float inner = boundsInner.max(i) - boundsInner.min(i);
if (inner < 0) {
continue;
}
float outer = bounds.max(i) - bounds.min(i);
float d = inner / outer;
if (d > best) {
best = d;
bestDim = i;
}
}
if (best <= 0) {
return null;
}
float min = boundsInner.min(bestDim);
float max = boundsInner.max(bestDim);
int firstIndex = -1, lastIndex = -1;
for (int i = 0; i < list.size() && (firstIndex < 0 || lastIndex < 0); i++) {
SpatialKey o = (SpatialKey) list.get(i);
if (firstIndex < 0 && o.max(bestDim) == min) {
firstIndex = i;
} else if (lastIndex < 0 && o.min(bestDim) == max) {
lastIndex = i;
}
}
return new int[] { firstIndex, lastIndex };
}
private void increaseMaxInnerBounds(Object bounds, Object add) {
SpatialKey b = (SpatialKey) bounds;
SpatialKey a = (SpatialKey) add;
for (int i = 0; i < dimensions; i++) {
b.setMin(i, Math.min(b.min(i), a.max(i)));
b.setMax(i, Math.max(b.max(i), a.min(i)));
}
}
}
......@@ -14,6 +14,7 @@ import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Random;
import java.util.TreeMap;
......@@ -26,6 +27,7 @@ import org.h2.jaqu.bytecode.Null;
import org.h2.store.fs.FileUtils;
import org.h2.test.TestBase;
import org.h2.util.New;
import org.h2.util.Profiler;
/**
* Tests the tree map store.
......@@ -42,8 +44,16 @@ public class TestBtreeMapStore extends TestBase {
}
public void test() {
testRtreeMany();
// testRtreeMany();
// System.out.println("lin: " + RtreeMap.splitLin + " quad:" + RtreeMap.splitQuad);
// testRtreeMany();
// System.out.println("lin: " + RtreeMap.splitLin + " quad:" + RtreeMap.splitQuad);
// testRtreeMany();
// System.out.println("lin: " + RtreeMap.splitLin + " quad:" + RtreeMap.splitQuad);
// if(true) return;
//
testRtree();
testRandomRtree();
testCustomMapType();
testTruncateFile();
testFastDelete();
......@@ -61,37 +71,113 @@ public class TestBtreeMapStore extends TestBase {
}
private void testRtreeMany() {
// quadratic:
// add: 796
// query: 161
// remove: 194
// linear: 50
// add: 345
// query: 244
// remove: 259
// MyTest
// add:197
// query:236
// delete:669
String fileName = getBaseDir() + "/testMeta.h3";
FileUtils.delete(fileName);
BtreeMapStore s;
s = openStore(fileName);
// s.setMaxPageSize(50);
s.setMaxPageSize(50);
RtreeMap<SpatialKey, String> r = s.openMap("data", "r", "s2", "");
// r.setQuadraticSplit(true);
Random rand = new Random(1);
int len = 1000;
int len = 1000000;
long t = System.currentTimeMillis();
Profiler prof = new Profiler();
//prof.startCollecting();
for (int i = 0; i < len; i++) {
float x = rand.nextFloat(), y = rand.nextFloat();
float p = (float) (rand.nextFloat() * 0.01);
SpatialKey k = SpatialKey.create(i, x - p, x + p, y - p, y + p);
r.put(k, "" + i);
if (i > 0 && (i % 100) == 0) {
s.store();
}
float p = (float) (rand.nextFloat() * 0.000001);
SpatialKey k = new SpatialKey(i, x - p, x + p, y - p, y + p);
r.add(k, "" + i);
if (i > 0 && (i % 10000) == 0) {
render(r, getBaseDir() + "/test.png");
s.store();
System.out.println("store " + i);
}
// if (i > 0 && (i % 10000) == 0) {
// render(r, getBaseDir() + "/test.png");
// }
}
//System.out.println(prof.getTop(5));
// quadratic
// add: 77967
// query: 39521
// remove: 22292
// linear
// add: 46136
// query: 65454
// remove: 35514
// > 10000 quadratic
// add: 54660
// query: 62946
System.out.println("add: " + (System.currentTimeMillis() - t));
s.store();
s.close();
s = openStore(fileName);
r = s.openMap("data", "r", "s2", "");
t = System.currentTimeMillis();
rand = new Random(1);
for (int i = 0; i < len; i++) {
float x = rand.nextFloat(), y = rand.nextFloat();
float p = (float) (rand.nextFloat() * 0.01);
SpatialKey k = SpatialKey.create(i, x - p, x + p, y - p, y + p);
float p = (float) (rand.nextFloat() * 0.000001);
SpatialKey k = new SpatialKey(i, x - p, x + p, y - p, y + p);
assertEquals("" + i, r.get(k));
}
System.out.println("query: " + (System.currentTimeMillis() - t));
assertEquals(len, r.size());
int count = 0;
for (SpatialKey k : r.keySet()) {
assertTrue(r.get(k) != null);
count++;
}
assertEquals(len, count);
t = System.currentTimeMillis();
//Profiler prof = new Profiler();
//prof.startCollecting();
rand = new Random(1);
for (int i = 0; i < len; i++) {
float x = rand.nextFloat(), y = rand.nextFloat();
float p = (float) (rand.nextFloat() * 0.000001);
SpatialKey k = new SpatialKey(i, x - p, x + p, y - p, y + p);
r.remove(k);
}
assertEquals(0, r.size());
// System.out.println(prof.getTop(5));
System.out.println("remove: " + (System.currentTimeMillis() - t));
}
private void testRtree() {
......@@ -130,7 +216,7 @@ public class TestBtreeMapStore extends TestBase {
float a = (float) ((int) x + (x - (int) x) * 5 / 3);
float b = 50 - (float) ((int) y + (y - (int) y) * 5 / 3);
float s = (float) Math.sqrt(population / 10000000.);
SpatialKey k = SpatialKey.create(id, a - s, a + s, b - s, b + s);
SpatialKey k = new SpatialKey(id, a - s, a + s, b - s, b + s);
r.put(k, name);
}
......@@ -145,13 +231,13 @@ public class TestBtreeMapStore extends TestBase {
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.BLACK);
SpatialKey b = SpatialKey.create(0, Float.MAX_VALUE, Float.MIN_VALUE,
SpatialKey b = new SpatialKey(0, Float.MAX_VALUE, Float.MIN_VALUE,
Float.MAX_VALUE, Float.MIN_VALUE);
for (SpatialKey x : r.keySet()) {
b.min[0] = Math.min(b.min[0], x.min[0]);
b.min[1] = Math.min(b.min[1], x.min[1]);
b.max[0] = Math.max(b.max[0], x.max[0]);
b.max[1] = Math.max(b.max[1], x.max[1]);
b.setMin(0, Math.min(b.min(0), x.min(0)));
b.setMin(1, Math.min(b.min(1), x.min(1)));
b.setMax(0, Math.max(b.max(0), x.max(0)));
b.setMax(1, Math.max(b.max(1), x.max(1)));
}
// System.out.println(b);
for (SpatialKey x : r.keySet()) {
......@@ -178,14 +264,55 @@ public class TestBtreeMapStore extends TestBase {
private static int[] scale(SpatialKey b, SpatialKey x, int width, int height) {
int[] rect = {
(int) ((x.min[0] - b.min[0]) * (width * 0.9) / (b.max[0] - b.min[0]) + width * 0.05),
(int) ((x.min[1] - b.min[1]) * (height * 0.9) / (b.max[1] - b.min[1]) + height * 0.05),
(int) ((x.max[0] - b.min[0]) * (width * 0.9) / (b.max[0] - b.min[0]) + width * 0.05),
(int) ((x.max[1] - b.min[1]) * (height * 0.9) / (b.max[1] - b.min[1]) + height * 0.05),
(int) ((x.min(1) - b.min(1)) * (height * 0.9) / (b.max(1) - b.min(1)) + height * 0.05),
(int) ((x.max(0) - b.min(0)) * (width * 0.9) / (b.max(0) - b.min(0)) + width * 0.05),
(int) ((x.max(1) - b.min(1)) * (height * 0.9) / (b.max(1) - b.min(1)) + height * 0.05),
};
return rect;
}
private void testRandomRtree() {
String fileName = getBaseDir() + "/testRandom.h3";
FileUtils.delete(fileName);
BtreeMapStore s = openStore(fileName);
RtreeMap<SpatialKey, String> m = s.openMap("data", "r", "s2", "");
HashMap<SpatialKey, String> map = new HashMap<SpatialKey, String>();
Random rand = new Random(1);
int operationCount = 1000;
int maxValue = 30;
for (int i = 0; i < operationCount; i++) {
int key = rand.nextInt(maxValue);
Random rk = new Random(key);
float x = rk.nextFloat(), y = rk.nextFloat();
float p = (float) (rk.nextFloat() * 0.000001);
SpatialKey k = new SpatialKey(key, x - p, x + p, y - p, y + p);
String v = "" + rand.nextInt();
switch (rand.nextInt(3)) {
case 0:
log(i + ": put " + k + " = " + v + " " + m.size());
m.put(k, v);
map.put(k, v);
break;
case 1:
log(i + ": remove " + k + " " + m.size());
m.remove(k);
map.remove(k);
break;
default:
String a = map.get(k);
String b = m.get(k);
if (a == null || b == null) {
assertTrue(a == b);
} else {
assertEquals(a, b);
}
break;
}
assertEquals(map.size(), m.size());
}
s.close();
}
private void testCustomMapType() {
String fileName = getBaseDir() + "/testMeta.h3";
FileUtils.delete(fileName);
......@@ -412,9 +539,10 @@ public class TestBtreeMapStore extends TestBase {
// s.setCompressor(null);
s.setMaxPageSize(40);
BtreeMap<Integer, Object[]> m = s.openMap("data", "", "i", "r(i,,)");
int i = 0;
// Profiler prof = new Profiler();
// prof.startCollecting();
// long t = System.currentTimeMillis();
for (; i < len;) {
for (int i = 0; i < len;) {
Object[] o = new Object[3];
o[0] = i;
o[1] = "Hello World";
......@@ -427,6 +555,7 @@ public class TestBtreeMapStore extends TestBase {
}
s.store();
s.close();
// System.out.println(prof.getTop(5));
// System.out.println("store time " + (System.currentTimeMillis() - t));
// System.out.println("store size " + FileUtils.size(fileName));
}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论