Skip to content

Commit 81a46be

Browse files
committed
性能优化,RTREE_PARENT_TO_CHILD关系变更在提交事务时再处理
1 parent 7997432 commit 81a46be

File tree

4 files changed

+95
-43
lines changed

4 files changed

+95
-43
lines changed

src/main/java/org/wowtools/neo4j/rtree/internal/edit/CacheNode.java

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -116,11 +116,8 @@ private Map<String, Object> getProperties(List<String> keys) {
116116
public void setProperty(String key, Object value) {
117117
changedKey.add(key);
118118
if (null == value) {
119-
// _node().removeProperty(key);
120-
// properties.remove(key);
121119
properties.put(key, empty);
122120
} else {
123-
// _node().setProperty(key, value);
124121
properties.put(key, value);
125122
}
126123
}
@@ -135,8 +132,12 @@ public org.wowtools.neo4j.rtree.internal.edit.Node[] getChildren() {
135132
int mMax = (int) getProperty("mMax");
136133
children = new org.wowtools.neo4j.rtree.internal.edit.Node[mMax];
137134
int i = 0;
135+
HashSet<Long> added = new HashSet<>();
138136
for (Relationship relationship : _node().getRelationships(Direction.OUTGOING, Relationships.RTREE_PARENT_TO_CHILD)) {
139137
children[i] = txCell.getNodeFromNeo4j(relationship.getEndNodeId());
138+
if (!added.add(relationship.getEndNodeId())) {
139+
throw new RuntimeException();
140+
}
140141
i++;
141142
}
142143
}
@@ -147,19 +148,43 @@ public org.wowtools.neo4j.rtree.internal.edit.Node[] getChildren() {
147148
public void setChildAtI(int i, org.wowtools.neo4j.rtree.internal.edit.Node node) {
148149
children = getChildren();
149150
org.wowtools.neo4j.rtree.internal.edit.Node old = children[i];
150-
Transaction tx = txCell.getTx();
151151
if (null != old) {
152152
//切断旧node的引用
153-
Node oldNode = tx.getNodeById(old.getNeoNodeId());
154-
oldNode.getRelationships(Direction.INCOMING, Relationships.RTREE_PARENT_TO_CHILD).forEach((r) -> {
155-
r.delete();
156-
});
153+
txCell.setNodeParent(old.getNeoNodeId(), null);
157154
}
158155
children[i] = node;
159156
if (null != node) {
160157
//建立新节点的引用
161-
Node neoNode = tx.getNodeById(node.getNeoNodeId());
162-
tx.getNodeById(nodeId).createRelationshipTo(neoNode, Relationships.RTREE_PARENT_TO_CHILD);
158+
txCell.setNodeParent(node.getNeoNodeId(), nodeId);
159+
160+
}
161+
162+
}
163+
164+
165+
/**
166+
* 把i+1位置开始,所有child的位置上移一位
167+
* 作用等同于System.arraycopy(child, i + 1, child, i, size - i - 1)
168+
*
169+
* @param i
170+
*/
171+
public void childIndexUp(int i) {
172+
int size = (int) getProperty("size");
173+
children = getChildren();
174+
175+
int j = i;
176+
int num = size - i - 1;
177+
for (int i1 = 0; i1 < num; i1++) {
178+
// setChildAtI(j, children[j + 1]);
179+
children[j] = children[j + 1];
180+
j++;
181+
}
182+
size--;
183+
setProperty("size", size);
184+
org.wowtools.neo4j.rtree.internal.edit.Node old = children[size];
185+
if (null != old) {
186+
txCell.setNodeParent(old.getNeoNodeId(), null);
187+
children[size] = null;
163188
}
164189

165190
}
@@ -180,24 +205,13 @@ public int addChild(final org.wowtools.neo4j.rtree.internal.edit.Node n) {
180205
mbr = n.getBound();
181206
}
182207
setMbr((RectNd) mbr);
183-
184-
// //建立新节点的引用
185-
// Transaction tx = txCell.getTx();
186-
// Node neoNode = tx.getNodeById(n.getNeoNodeId());
187-
//
188-
// neoNode.getRelationships(Direction.INCOMING, Relationships.RTREE_PARENT_TO_CHILD).forEach((r) -> {
189-
// r.delete();
190-
// });
191-
// tx.getNodeById(nodeId).createRelationshipTo(neoNode, Relationships.RTREE_PARENT_TO_CHILD);
192-
193208
return size - 1;
194209
} else {
195210
throw new RuntimeException("Too many children");
196211
}
197212
}
198213

199214

200-
201215
public RectNd[] getEntry() {
202216
if (null == entry) {
203217
int mMax = (int) getProperty("mMax");

src/main/java/org/wowtools/neo4j/rtree/internal/edit/NodeOfBranch.java

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -143,15 +143,8 @@ public Node remove(final RectNd t) {
143143
if (child[i] == null) {
144144
// System.arraycopy(child, i + 1, child, i, size - i - 1);
145145
//把所有child的位置上移一位
146-
int j = i;
147-
int num = size - i - 1;
148-
for (int i1 = 0; i1 < num; i1++) {
149-
cacheNode.setChildAtI(j, child[j + 1]);
150-
j++;
151-
}
152-
size--;
153-
cacheNode.setChildAtI(size, null);
154-
146+
cacheNode.childIndexUp(i);
147+
size = (int) cacheNode.getProperty("size");
155148
if (size > 0) i--;
156149
}
157150
}
@@ -185,10 +178,10 @@ public Node update(final RectNd told, final RectNd tnew) {
185178
RectNd mbr = cacheNode.getMbr();
186179
if (i == 0) {
187180
mbr = child[i].getBound();
188-
cacheNode.setMbr((RectNd) mbr);
181+
cacheNode.setMbr( mbr);
189182
} else {
190183
mbr = mbr.getMbr(child[i].getBound());
191-
cacheNode.setMbr((RectNd) mbr);
184+
cacheNode.setMbr( mbr);
192185
}
193186
}
194187
return this;

src/main/java/org/wowtools/neo4j/rtree/util/TxCell.java

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ public class TxCell {
3434

3535
private final Map<Long, CacheNode> cacheNodeMap = new HashMap<>();
3636

37+
private final Map<Long, Long> nodeParentMap = new HashMap<>();
38+
3739
public CacheNode getNode(long nodeId) {
3840
CacheNode cacheNode = cacheNodeMap.get(nodeId);
3941
if (null != cacheNode) {
@@ -68,6 +70,10 @@ public CacheNode newNode(Label label) {
6870
return cacheNode;
6971
}
7072

73+
public void setNodeParent(Long nodeId, Long parentNodeId) {
74+
nodeParentMap.put(nodeId, parentNodeId);
75+
}
76+
7177
public org.wowtools.neo4j.rtree.internal.edit.Node getNodeFromNeo4j(long nid) {
7278
Node node = getTx().getNodeById(nid);
7379
String labelName = node.getLabels().iterator().next().name();
@@ -121,16 +127,43 @@ public boolean limitCommit() {
121127
}
122128

123129
public void commit() {
130+
//各cacheNode属性提交
124131
cacheNodeMap.forEach((nid, cacheNode) -> {
125132
cacheNode.commit();
126133
});
127-
neoGc();
128-
tx.commit();
134+
//RTREE_PARENT_TO_CHILD关系变更
135+
nodeParentMap.forEach((nid, parentNid) -> {
136+
if (null == parentNid) {//parentNid为空,删除旧关系
137+
for (Relationship relationship : tx.getNodeById(nid).getRelationships(Direction.INCOMING, Relationships.RTREE_PARENT_TO_CHILD)) {
138+
relationship.delete();
139+
}
140+
} else {//parentNid非空,修改关系
141+
boolean hasRelationship = false;//新的关系是否已存在
142+
for (Relationship relationship : tx.getNodeById(nid).getRelationships(Direction.INCOMING, Relationships.RTREE_PARENT_TO_CHILD)) {
143+
if (hasRelationship) {
144+
relationship.delete();
145+
} else {
146+
if (parentNid == relationship.getStartNodeId()) {
147+
hasRelationship = true;
148+
} else {
149+
relationship.delete();
150+
}
151+
}
152+
}
153+
if (null != parentNid && !hasRelationship) {
154+
tx.getNodeById(parentNid).createRelationshipTo(tx.getNodeById(nid), Relationships.RTREE_PARENT_TO_CHILD);
155+
}
156+
}
157+
});
158+
neoGc();//gc
159+
tx.commit();//提交neo4j事务
160+
//清理内存中的对象
129161
num = 0;
130162
cacheNodeMap.forEach((nid, cacheNode) -> {
131163
cacheNode.clearCache();
132164
});
133165
cacheNodeMap.clear();
166+
nodeParentMap.clear();
134167
}
135168

136169
/**

src/test/java/org/wowtools/neo4j/rtree/RtreeEditorTest.java

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,15 @@ public class RtreeEditorTest {
2121
private Neo4jDbManager neo4jDbManager;
2222

2323
@Before
24-
public void before(){
24+
public void before() {
2525
neo4jDbManager = new Neo4jDbManager();
2626
}
2727

2828
@After
29-
public void after(){
29+
public void after() {
3030
neo4jDbManager.afterTest();
3131
}
32+
3233
@Test
3334
public void test() {
3435
//构造测试数据
@@ -75,44 +76,49 @@ public void test() {
7576
}
7677

7778
// add
79+
long t = System.currentTimeMillis();
7880
try (RtreeEditor rtreeEditor = RtreeEditor.create(neo4jDbManager.getGraphDb(), 2000, indexName, 2, 8)) {
7981
for (int i = 0; i < num; i++) {
8082
rtreeEditor.add(rectNds[i]);
8183
}
8284
}
85+
long t1 = System.currentTimeMillis() - t;
8386
MyVisitor myVisitor = new MyVisitor();
8487
try (Transaction tx = neo4jDbManager.getGraphDb().beginTx()) {
8588
RtreeIntersectsSearcher searcher = RtreeIntersectsSearcher.get(tx, indexName);
8689
PointNd p0 = new PointNd(new double[]{x0, y0});
8790
PointNd p1 = new PointNd(new double[]{x1, y1});
8891
searcher.intersects(new RectNd(p0, p1), tx, myVisitor);
8992
}
90-
System.out.println("add " + myVisitor.num);
93+
System.out.println("add " + myVisitor.num + ",cost " + t1);
9194
Assert.assertEquals(resNum, myVisitor.num);
9295
// end add
9396

9497
// remove
9598
int removeNum = (int) (resNum * 0.4);//移除40%的数据
9699
resNum -= removeNum;
100+
t = System.currentTimeMillis();
97101
try (RtreeEditor rtreeEditor = RtreeEditor.get(neo4jDbManager.getGraphDb(), 2000, indexName)) {
98102
for (int i = 0; i < removeNum; i++) {
99103
RectNd rn = intersectRectNds.get(i);
100104
rtreeEditor.remove(rn);
101105
}
102106
}
107+
t1 = System.currentTimeMillis() - t;
103108
myVisitor = new MyVisitor();
104109
try (Transaction tx = neo4jDbManager.getGraphDb().beginTx()) {
105110
RtreeIntersectsSearcher searcher = RtreeIntersectsSearcher.get(tx, indexName);
106111
PointNd p0 = new PointNd(new double[]{x0, y0});
107112
PointNd p1 = new PointNd(new double[]{x1, y1});
108113
searcher.intersects(new RectNd(p0, p1), tx, myVisitor);
109114
}
110-
System.out.println("remove " + myVisitor.num);
115+
System.out.println("remove " + myVisitor.num + ",cost " + t1);
111116
Assert.assertEquals(resNum, myVisitor.num);
112117
// end remove
113118

114119
// update
115120
int updateStart = removeNum + 1;
121+
t = System.currentTimeMillis();
116122
try (RtreeEditor rtreeEditor = RtreeEditor.get(neo4jDbManager.getGraphDb(), 2000, indexName)) {
117123
for (int i = updateStart; i < intersectRectNds.size(); i++) {
118124
RectNd told = intersectRectNds.get(i);
@@ -137,15 +143,15 @@ public void test() {
137143
rtreeEditor.update(told, rect2d);
138144
}
139145
}
140-
146+
t1 = System.currentTimeMillis() - t;
141147
myVisitor = new MyVisitor();
142148
try (Transaction tx = neo4jDbManager.getGraphDb().beginTx()) {
143149
RtreeIntersectsSearcher searcher = RtreeIntersectsSearcher.get(tx, indexName);
144150
PointNd p0 = new PointNd(new double[]{x0, y0});
145151
PointNd p1 = new PointNd(new double[]{x1, y1});
146152
searcher.intersects(new RectNd(p0, p1), tx, myVisitor);
147153
}
148-
System.out.println("update " + myVisitor.num);
154+
System.out.println("update " + myVisitor.num+ ",cost " + t1);
149155
Assert.assertEquals(resNum, myVisitor.num);
150156
// end update
151157

@@ -157,9 +163,15 @@ public void test() {
157163
});
158164
}
159165
try (Transaction tx = neo4jDbManager.getGraphDb().beginTx()) {
160-
tx.findNodes(Labels.METADATA).forEachRemaining(node -> {throw new RuntimeException("drop未清理干净");});
161-
tx.findNodes(Labels.RTREE_BRANCH).forEachRemaining(node -> {throw new RuntimeException("drop未清理干净");});
162-
tx.findNodes(Labels.RTREE_LEAF).forEachRemaining(node -> {throw new RuntimeException("drop未清理干净");});
166+
tx.findNodes(Labels.METADATA).forEachRemaining(node -> {
167+
throw new RuntimeException("drop未清理干净");
168+
});
169+
tx.findNodes(Labels.RTREE_BRANCH).forEachRemaining(node -> {
170+
throw new RuntimeException("drop未清理干净");
171+
});
172+
tx.findNodes(Labels.RTREE_LEAF).forEachRemaining(node -> {
173+
throw new RuntimeException("drop未清理干净");
174+
});
163175
}
164176
// drop end
165177

0 commit comments

Comments
 (0)