Skip to content

Commit 04fe661

Browse files
committed
Split non-leaf - BranchNode from leaf nodes (to reduce memory footprint)
Move branch-specific methods to BranchNode replace checks for LEAF_NODE with instanceof checks make some leaf-node-specific code to conditional
1 parent a71bb24 commit 04fe661

18 files changed

Lines changed: 493 additions & 511 deletions

File tree

roaringbitmap/src/main/java/org/roaringbitmap/art/AbstractShuttle.java

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -51,32 +51,29 @@ public boolean moveToNextLeaf() {
5151
if (!hasRun) {
5252
hasRun = true;
5353
Node node = stack[depth].node;
54-
if (node.nodeType == NodeType.LEAF_NODE) {
55-
return true;
56-
} else {
57-
return false;
58-
}
54+
return node instanceof LeafNode;
5955
}
6056
// skip the top leaf node
6157
Node node = stack[depth].node;
62-
if (node.nodeType == NodeType.LEAF_NODE) {
58+
if (node instanceof LeafNode) {
6359
depth--;
6460
}
6561
// visit parent node
6662
while (depth >= 0) {
6763
NodeEntry currentNodeEntry = stack[depth];
68-
if (currentNodeEntry.node.nodeType == NodeType.LEAF_NODE) {
64+
if (currentNodeEntry.node instanceof LeafNode) {
6965
// found current leaf node's next sibling node to benefit the removing operation
7066
if (depth - 1 >= 0) {
7167
findNextSiblingKeyOfLeafNode();
7268
}
7369
return true;
7470
}
7571
// visit the next child node
72+
BranchNode currentBranchNode = (BranchNode) currentNodeEntry.node;
7673
int pos;
7774
int nextPos;
7875
if (!currentNodeEntry.visited) {
79-
pos = boundaryNodePosition(currentNodeEntry.node, false);
76+
pos = boundaryNodePosition(currentBranchNode, false);
8077
currentNodeEntry.position = pos;
8178
nextPos = pos;
8279
currentNodeEntry.visited = true;
@@ -85,14 +82,14 @@ public boolean moveToNextLeaf() {
8582
currentNodeEntry.startFromNextSiblingPosition = false;
8683
} else {
8784
pos = currentNodeEntry.position;
88-
nextPos = visitedNodeNextPosition(currentNodeEntry.node, pos);
85+
nextPos = visitedNodeNextPosition(currentBranchNode, pos);
8986
}
90-
if (nextPos != Node.ILLEGAL_IDX) {
87+
if (nextPos != BranchNode.ILLEGAL_IDX) {
9188
stack[depth].position = nextPos;
9289
depth++;
9390
// add a fresh entry on the top of the visiting stack
9491
NodeEntry freshEntry = new NodeEntry();
95-
freshEntry.node = currentNodeEntry.node.getChild(nextPos);
92+
freshEntry.node = currentBranchNode.getChild(nextPos);
9693
stack[depth] = freshEntry;
9794
} else {
9895
// current internal node doesn't have anymore unvisited child,move to a top node
@@ -102,7 +99,7 @@ public boolean moveToNextLeaf() {
10299
return false;
103100
}
104101

105-
protected abstract int visitedNodeNextPosition(Node node, int pos);
102+
protected abstract int visitedNodeNextPosition(BranchNode node, int pos);
106103

107104
@Override
108105
public LeafNode getCurrentLeafNode() {
@@ -128,8 +125,8 @@ public void remove() {
128125
oldEntry.visited = oldEntry.node == node;
129126
oldEntry.node = node;
130127
oldEntry.startFromNextSiblingPosition = true;
131-
if (node.nodeType != NodeType.LEAF_NODE) {
132-
oldEntry.position = node.getChildPos(oldEntry.leafNodeNextSiblingKey);
128+
if (node instanceof BranchNode) {
129+
oldEntry.position = ((BranchNode)node).getChildPos(oldEntry.leafNodeNextSiblingKey);
133130
}
134131
}
135132
}
@@ -144,7 +141,7 @@ private void visitToLeaf(Node node, boolean inRunDirection) {
144141
this.depth = 0;
145142
stack[depth] = nodeEntry;
146143
}
147-
if (node.nodeType == NodeType.LEAF_NODE) {
144+
if (node instanceof LeafNode) {
148145
// leaf node's corresponding NodeEntry will not have the position member set.
149146
if (depth - 1 >= 0) {
150147
findNextSiblingKeyOfLeafNode();
@@ -154,11 +151,12 @@ private void visitToLeaf(Node node, boolean inRunDirection) {
154151
if (depth == MAX_DEPTH) {
155152
return;
156153
}
154+
BranchNode branchNode = (BranchNode) node;
157155
// find next min child
158-
int pos = boundaryNodePosition(node, inRunDirection);
156+
int pos = boundaryNodePosition(branchNode, inRunDirection);
159157
stack[depth].position = pos;
160158
stack[depth].visited = true;
161-
Node child = node.getChild(pos);
159+
Node child = branchNode.getChild(pos);
162160
NodeEntry childNodeEntry = new NodeEntry();
163161
childNodeEntry.node = child;
164162
this.depth++;
@@ -176,7 +174,7 @@ private void visitToLeafFrom(byte[] high, int keyDepth, Node node) {
176174
this.depth = 0;
177175
stack[depth] = nodeEntry;
178176
}
179-
if (node.nodeType == NodeType.LEAF_NODE) {
177+
if (node instanceof LeafNode) {
180178
// leaf node's corresponding NodeEntry will not have the position member set.
181179
if (depth - 1 >= 0) {
182180
findNextSiblingKeyOfLeafNode();
@@ -187,22 +185,24 @@ private void visitToLeafFrom(byte[] high, int keyDepth, Node node) {
187185
return;
188186
}
189187

190-
if (node.prefixLength > 0) {
188+
BranchNode branchNode = (BranchNode) node;
189+
190+
if (branchNode.prefixLength > 0) {
191191
int commonLength =
192-
Art.commonPrefixLength(high, keyDepth, high.length, node.prefix, 0, node.prefixLength);
193-
if (commonLength != node.prefixLength) {
194-
byte nodeValue = node.prefix[commonLength];
192+
Art.commonPrefixLength(high, keyDepth, high.length, branchNode.prefix, 0, branchNode.prefixLength);
193+
if (commonLength != branchNode.prefixLength) {
194+
byte nodeValue = branchNode.prefix[commonLength];
195195
byte highValue = high[keyDepth + commonLength];
196196
boolean visitDirection = prefixMismatchIsInRunDirection(nodeValue, highValue);
197197
// once we miss a single match, there's no point comparing parts of the key anymore
198198
visitToLeaf(node, visitDirection);
199199
return;
200200
}
201201
// common prefix is the same ,then increase the depth
202-
keyDepth += node.prefixLength;
202+
keyDepth += branchNode.prefixLength;
203203
}
204204
// find next child
205-
SearchResult result = node.getNearestChildPos(high[keyDepth]);
205+
SearchResult result = branchNode.getNearestChildPos(high[keyDepth]);
206206
int pos;
207207
boolean continueAtBoundary = false;
208208
boolean continueInRunDirection = false;
@@ -213,8 +213,8 @@ private void visitToLeafFrom(byte[] high, int keyDepth, Node node) {
213213
case NOT_FOUND:
214214
pos = searchMissNextPosition(result);
215215
continueAtBoundary = true;
216-
if (pos == Node.ILLEGAL_IDX) {
217-
pos = boundaryNodePosition(node, true);
216+
if (pos == BranchNode.ILLEGAL_IDX) {
217+
pos = boundaryNodePosition(branchNode, true);
218218
continueInRunDirection = true;
219219
}
220220
break;
@@ -223,7 +223,7 @@ private void visitToLeafFrom(byte[] high, int keyDepth, Node node) {
223223
}
224224
stack[depth].position = pos;
225225
stack[depth].visited = true;
226-
Node child = node.getChild(pos);
226+
Node child = branchNode.getChild(pos);
227227
NodeEntry childNodeEntry = new NodeEntry();
228228
childNodeEntry.node = child;
229229
this.depth++;
@@ -237,24 +237,24 @@ private void visitToLeafFrom(byte[] high, int keyDepth, Node node) {
237237
}
238238
}
239239

240-
protected abstract int boundaryNodePosition(Node node, boolean inRunDirection);
240+
protected abstract int boundaryNodePosition(BranchNode node, boolean inRunDirection);
241241

242242
protected abstract boolean prefixMismatchIsInRunDirection(byte nodeValue, byte highValue);
243243

244244
protected abstract int searchMissNextPosition(SearchResult result);
245245

246246
private void findNextSiblingKeyOfLeafNode() {
247-
Node parentNode = stack[depth - 1].node;
247+
BranchNode parentNode = (BranchNode) stack[depth - 1].node;
248248
int nextSiblingPos = visitedNodeNextPosition(parentNode, stack[depth - 1].position);
249-
if (nextSiblingPos != Node.ILLEGAL_IDX) {
249+
if (nextSiblingPos != BranchNode.ILLEGAL_IDX) {
250250
byte nextSiblingKey = parentNode.getChildKey(nextSiblingPos);
251251
stack[depth - 1].leafNodeNextSiblingKey = nextSiblingKey;
252252
}
253253
}
254254

255255
class NodeEntry {
256256
Node node = null;
257-
int position = Node.ILLEGAL_IDX;
257+
int position = BranchNode.ILLEGAL_IDX;
258258
boolean visited = false;
259259
boolean startFromNextSiblingPosition = false;
260260
byte leafNodeNextSiblingKey;

0 commit comments

Comments
 (0)