Skip to content

Commit 3f143da

Browse files
committed
improve path parser
1 parent 6355b0d commit 3f143da

1 file changed

Lines changed: 277 additions & 37 deletions

File tree

client/src/main/java/com/vesoft/nebula/driver/graph/decode/ValueParser.java

Lines changed: 277 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -128,16 +128,56 @@ public class ValueParser {
128128
private ByteOrder byteOrder;
129129

130130
private static final byte[] kOneBitmasks = {
131-
(byte) (1 << 0), // 0000 0001
132-
(byte) (1 << 1), // 0000 0010
133-
(byte) (1 << 2), // 0000 0100
134-
(byte) (1 << 3), // 0000 1000
135-
(byte) (1 << 4), // 0001 0000
136-
(byte) (1 << 5), // 0010 0000
137-
(byte) (1 << 6), // 0100 0000
138-
(byte) (1 << 7) // 1000 0000
131+
(byte) (1 << 0), // 0000 0001
132+
(byte) (1 << 1), // 0000 0010
133+
(byte) (1 << 2), // 0000 0100
134+
(byte) (1 << 3), // 0000 1000
135+
(byte) (1 << 4), // 0001 0000
136+
(byte) (1 << 5), // 0010 0000
137+
(byte) (1 << 6), // 0100 0000
138+
(byte) (1 << 7) // 1000 0000
139139
};
140140

141+
/**
142+
* Cache for node property information to optimize repeated lookups in Path decoding.
143+
*/
144+
private static class NodePropCache {
145+
int graphId;
146+
int nodeTypeId;
147+
List<String> propNames;
148+
List<DataType> propTypes;
149+
List<Integer> propVectorIndices;
150+
151+
NodePropCache(int graphId, int nodeTypeId, List<String> propNames,
152+
List<DataType> propTypes, List<Integer> propVectorIndices) {
153+
this.graphId = graphId;
154+
this.nodeTypeId = nodeTypeId;
155+
this.propNames = propNames;
156+
this.propTypes = propTypes;
157+
this.propVectorIndices = propVectorIndices;
158+
}
159+
}
160+
161+
/**
162+
* Cache for edge property information to optimize repeated lookups in Path decoding.
163+
*/
164+
private static class EdgePropCache {
165+
int graphId;
166+
int edgeTypeId;
167+
List<String> propNames;
168+
List<DataType> propTypes;
169+
List<Integer> propVectorIndices;
170+
171+
EdgePropCache(int graphId, int edgeTypeId, List<String> propNames,
172+
List<DataType> propTypes, List<Integer> propVectorIndices) {
173+
this.graphId = graphId;
174+
this.edgeTypeId = edgeTypeId;
175+
this.propNames = propNames;
176+
this.propTypes = propTypes;
177+
this.propVectorIndices = propVectorIndices;
178+
}
179+
}
180+
141181

142182
public ValueParser(ResultGraphSchemas graphSchemas,
143183
int timeZoneOffset,
@@ -415,10 +455,88 @@ private Object decodeFlatValue(VectorWrapper vector,
415455
Map<Integer, Map<Integer, Integer>> edgeTypes =
416456
pathSpecialMetaData.getGraphIdAndEdgeTypes();
417457

418-
// construct map: uint16 pair index-> (node vector, adj vector)
419-
Map<Integer, PathVectorPair> indexAndNodes = pathSpecialMetaData.getIndexAndNodes();
420-
// construct map: uint16 pair index-> (edge vector, adj vector)
421-
Map<Integer, PathVectorPair> indexAndEdges = pathSpecialMetaData.getIndexAndEdges();
458+
// Pre-compute property caches for all node and edge types in this path
459+
// This avoids repeated HashMap lookups during node/edge decoding
460+
Map<String, NodePropCache> nodePropCacheMap = new HashMap<>();
461+
Map<String, EdgePropCache> edgePropCacheMap = new HashMap<>();
462+
463+
// Pre-compute node property caches
464+
Map<Integer, Map<Integer, Map<String, DataType>>> pathNodePropColumnType =
465+
pathType.getNodeTypes();
466+
Map<Integer, Map<Integer, Map<String, Integer>>> pathNodePropVectorIndex =
467+
vector.getGraphElementTypeIdAndPropVectorIndexMap(NODE_TYPE_ID_SIZE);
468+
469+
for (Map.Entry<Integer, Map<Integer, Integer>> graphEntry
470+
: nodeTypes.entrySet()) {
471+
int graphId = graphEntry.getKey();
472+
for (Map.Entry<Integer, Integer> typeEntry
473+
: graphEntry.getValue().entrySet()) {
474+
int nodeTypeId = typeEntry.getKey();
475+
String cacheKey = graphId + "_" + nodeTypeId;
476+
477+
if (!pathNodePropColumnType.containsKey(graphId)
478+
|| !pathNodePropColumnType.get(graphId).containsKey(nodeTypeId)) {
479+
continue;
480+
}
481+
482+
Map<String, DataType> nodePropTypeMap =
483+
pathNodePropColumnType.get(graphId).get(nodeTypeId);
484+
Map<String, Integer> propVectorIndexMap =
485+
pathNodePropVectorIndex.get(graphId).get(nodeTypeId);
486+
487+
List<String> propNames = new ArrayList<>(nodePropTypeMap.keySet());
488+
List<DataType> propTypes = new ArrayList<>();
489+
List<Integer> propVectorIndices = new ArrayList<>();
490+
491+
for (String propName : propNames) {
492+
propTypes.add(nodePropTypeMap.get(propName));
493+
propVectorIndices.add(propVectorIndexMap.get(propName));
494+
}
495+
496+
nodePropCacheMap.put(cacheKey,
497+
new NodePropCache(graphId, nodeTypeId,
498+
propNames, propTypes, propVectorIndices));
499+
}
500+
}
501+
502+
// Pre-compute edge property caches
503+
Map<Integer, Map<Integer, Map<String, DataType>>> pathEdgePropColumnType =
504+
pathType.getEdgeTypes();
505+
Map<Integer, Map<Integer, Map<String, Integer>>> pathEdgePropVectorIndex =
506+
vector.getGraphElementTypeIdAndPropVectorIndexMap(EDGE_TYPE_ID_SIZE);
507+
508+
for (Map.Entry<Integer, Map<Integer, Integer>> graphEntry
509+
: edgeTypes.entrySet()) {
510+
int graphId = graphEntry.getKey();
511+
for (Map.Entry<Integer, Integer> typeEntry
512+
: graphEntry.getValue().entrySet()) {
513+
int edgeTypeId = typeEntry.getKey();
514+
String cacheKey = graphId + "_" + edgeTypeId;
515+
516+
if (!pathEdgePropColumnType.containsKey(graphId)
517+
|| !pathEdgePropColumnType.get(graphId).containsKey(edgeTypeId)) {
518+
continue;
519+
}
520+
521+
Map<String, DataType> pathEdgePropTypeMap =
522+
pathEdgePropColumnType.get(graphId).get(edgeTypeId);
523+
Map<String, Integer> propVectorIndexMap =
524+
pathEdgePropVectorIndex.get(graphId).get(edgeTypeId);
525+
526+
List<String> propNames = new ArrayList<>(pathEdgePropTypeMap.keySet());
527+
List<DataType> propTypes = new ArrayList<>();
528+
List<Integer> propVectorIndices = new ArrayList<>();
529+
530+
for (String propName : propNames) {
531+
propTypes.add(pathEdgePropTypeMap.get(propName));
532+
propVectorIndices.add(propVectorIndexMap.get(propName));
533+
}
534+
535+
edgePropCacheMap.put(cacheKey,
536+
new EdgePropCache(graphId, edgeTypeId,
537+
propNames, propTypes, propVectorIndices));
538+
}
539+
}
422540

423541
// decode path value
424542
List<ValueWrapper> elements = new ArrayList<>();
@@ -429,50 +547,51 @@ private Object decodeFlatValue(VectorWrapper vector,
429547
if (pathHeader.getSize() <= 0) {
430548
return new Path(elements);
431549
}
550+
551+
// construct map: uint16 pair index-> (node vector, adj vector)
552+
final Map<Integer, PathVectorPair> indexAndNodes =
553+
pathSpecialMetaData.getIndexAndNodes();
554+
// construct map: uint16 pair index-> (edge vector, adj vector)
555+
final Map<Integer, PathVectorPair> indexAndEdges =
556+
pathSpecialMetaData.getIndexAndEdges();
557+
432558
// decode the first node of path
433-
PathVectorPair firstNodePair = indexAndNodes.get(pathHeader.getHeadNodeIndex());
559+
PathVectorPair firstNodePair =
560+
indexAndNodes.get(pathHeader.getHeadNodeIndex());
434561
VectorWrapper firstNodeVector = firstNodePair.getVector();
435562
VectorWrapper firstNodeAdjVector = firstNodePair.getAdjVector();
436-
firstNode = decodeValue(firstNodeVector,
437-
pathType.getDataTypes().get(0),
438-
pathHeader.getHeadOffset());
563+
firstNode = decodeNodeForPath(firstNodeVector, nodePropCacheMap,
564+
pathHeader.getHeadOffset());
439565
elements.add(new ValueWrapper(firstNode, ColumnType.COLUMN_TYPE_NODE));
440-
PathAdjHeader pathAdjHeader = new PathAdjHeader(bytesToInt64(getSubBytes(firstNodeAdjVector.getVectorData(),
441-
INT64_SIZE,
442-
pathHeader.getHeadOffset()),
443-
byteOrder));
566+
PathAdjHeader pathAdjHeader = new PathAdjHeader(
567+
bytesToInt64(getSubBytes(firstNodeAdjVector.getVectorData(),
568+
INT64_SIZE, pathHeader.getHeadOffset()), byteOrder));
444569

445570
VectorWrapper adjVector = null;
446-
final EdgeType pathEdgeType = new EdgeType(pathType.getEdgeTypes());
447-
final NodeType pathNodeType = new NodeType(pathType.getNodeTypes());
448571

449572
while (!pathAdjHeader.isEnd()) {
450-
int vecIndex = pathAdjHeader.getVecIdxOfNextEle();
573+
int vecIndex = pathAdjHeader.getVecIdxOfNextEle();
451574
int vecOffset = pathAdjHeader.getOffsetOfNextEle();
452575
if (pathAdjHeader.isNextEdge()) {
453576
PathVectorPair edgeVectorPair = indexAndEdges.get(vecIndex);
454-
Object edge = decodeValue(edgeVectorPair.getVector(),
455-
pathEdgeType,
456-
vecOffset);
577+
Object edge = decodeEdgeForPath(edgeVectorPair.getVector(),
578+
edgePropCacheMap, vecOffset);
457579
adjVector = edgeVectorPair.getAdjVector();
458580
elements.add(new ValueWrapper(edge, ColumnType.COLUMN_TYPE_EDGE));
459581
// update the adj header
460-
pathAdjHeader = new PathAdjHeader(bytesToInt64(getSubBytes(adjVector.getVectorData(),
461-
INT64_SIZE,
462-
vecOffset),
463-
byteOrder));
582+
pathAdjHeader = new PathAdjHeader(
583+
bytesToInt64(getSubBytes(adjVector.getVectorData(),
584+
INT64_SIZE, vecOffset), byteOrder));
464585
} else {
465586
PathVectorPair nodeVectorPair = indexAndNodes.get(vecIndex);
466-
Object node = decodeValue(nodeVectorPair.getVector(),
467-
pathNodeType,
468-
vecOffset);
587+
Object node = decodeNodeForPath(nodeVectorPair.getVector(),
588+
nodePropCacheMap, vecOffset);
469589
adjVector = nodeVectorPair.getAdjVector();
470590
elements.add(new ValueWrapper(node, ColumnType.COLUMN_TYPE_NODE));
471591
// update the adj header
472-
pathAdjHeader = new PathAdjHeader(bytesToInt64(getSubBytes(adjVector.getVectorData(),
473-
INT64_SIZE,
474-
vecOffset),
475-
byteOrder));
592+
pathAdjHeader = new PathAdjHeader(
593+
bytesToInt64(getSubBytes(adjVector.getVectorData(),
594+
INT64_SIZE, vecOffset), byteOrder));
476595
}
477596
}
478597
return new Path(elements);
@@ -607,6 +726,127 @@ public String bytesToString(ByteString stringHeader, NestedVector vector) {
607726
return valueData.toString(charset);
608727
}
609728

729+
/**
730+
* Decode node properties using pre-computed cache for optimization.
731+
*
732+
* @param vector the vector wrapper
733+
* @param nodeCache the node property cache
734+
* @param rowIndex the row index
735+
* @return map of property name to value wrapper
736+
*/
737+
private Map<String, ValueWrapper> decodeNodePropsWithCache(VectorWrapper vector,
738+
NodePropCache nodeCache,
739+
int rowIndex) {
740+
Map<String, ValueWrapper> props = new HashMap<>(nodeCache.propNames.size());
741+
for (int i = 0; i < nodeCache.propNames.size(); i++) {
742+
String propName = nodeCache.propNames.get(i);
743+
DataType propType = nodeCache.propTypes.get(i);
744+
int vectorIndex = nodeCache.propVectorIndices.get(i);
745+
746+
Object propValue = decodeValue(vector.getVectorWrapper(vectorIndex),
747+
propType,
748+
rowIndex);
749+
props.put(propName, new ValueWrapper(propValue, propType.getType()));
750+
}
751+
return props;
752+
}
753+
754+
/**
755+
* Decode edge properties using pre-computed cache for optimization.
756+
*
757+
* @param vector the vector wrapper
758+
* @param edgeCache the edge property cache
759+
* @param rowIndex the row index
760+
* @return map of property name to value wrapper
761+
*/
762+
private Map<String, ValueWrapper> decodeEdgePropsWithCache(VectorWrapper vector,
763+
EdgePropCache edgeCache,
764+
int rowIndex) {
765+
Map<String, ValueWrapper> props = new HashMap<>(edgeCache.propNames.size());
766+
for (int i = 0; i < edgeCache.propNames.size(); i++) {
767+
String propName = edgeCache.propNames.get(i);
768+
DataType propType = edgeCache.propTypes.get(i);
769+
int vectorIndex = edgeCache.propVectorIndices.get(i);
770+
771+
Object propValue = decodeValue(vector.getVectorWrapper(vectorIndex),
772+
propType,
773+
rowIndex);
774+
props.put(propName, new ValueWrapper(propValue, propType.getType()));
775+
}
776+
return props;
777+
}
778+
779+
/**
780+
* Decode a node for Path using pre-computed cache for optimization.
781+
*
782+
* @param vector the vector wrapper
783+
* @param nodePropCacheMap the node property cache map
784+
* @param rowIndex the row index
785+
* @return the decoded node
786+
*/
787+
private Node decodeNodeForPath(VectorWrapper vector,
788+
Map<String, NodePropCache> nodePropCacheMap,
789+
int rowIndex) {
790+
ByteString vectorData = vector.getVectorData();
791+
ByteString nodeHeaderBinary = getSubBytes(vectorData,
792+
VECTOR_NODE_HEADER_SIZE,
793+
rowIndex);
794+
NodeHeader nodeHeader = new NodeHeader(nodeHeaderBinary, byteOrder);
795+
796+
String cacheKey = nodeHeader.getGraphId() + "_" + nodeHeader.getNodeTypeId();
797+
NodePropCache nodeCache = nodePropCacheMap.get(cacheKey);
798+
799+
if (nodeCache == null) {
800+
throw new RuntimeException(String.format(
801+
"Node cache not found for graphId %d, nodeTypeId %d",
802+
nodeHeader.getGraphId(), nodeHeader.getNodeTypeId()));
803+
}
804+
805+
Map<String, ValueWrapper> props = decodeNodePropsWithCache(vector, nodeCache, rowIndex);
806+
return new Node(nodeHeader.getGraphId(),
807+
nodeHeader.getNodeTypeId(),
808+
nodeHeader.getNodeId(),
809+
props,
810+
graphSchemas);
811+
}
812+
813+
/**
814+
* Decode an edge for Path using pre-computed cache for optimization.
815+
*
816+
* @param vector the vector wrapper
817+
* @param edgePropCacheMap the edge property cache map
818+
* @param rowIndex the row index
819+
* @return the decoded edge
820+
*/
821+
private Edge decodeEdgeForPath(VectorWrapper vector,
822+
Map<String, EdgePropCache> edgePropCacheMap,
823+
int rowIndex) {
824+
ByteString vectorData = vector.getVectorData();
825+
ByteString edgeHeaderBinary = getSubBytes(vectorData,
826+
VECTOR_EDGE_HEADER_SIZE,
827+
rowIndex);
828+
EdgeHeader edgeHeader = new EdgeHeader(edgeHeaderBinary, byteOrder);
829+
830+
int noDirectedTypeId = edgeHeader.getEdgeTypeId() & 0x3FFFFFFF;
831+
String cacheKey = edgeHeader.getGraphId() + "_" + noDirectedTypeId;
832+
EdgePropCache edgeCache = edgePropCacheMap.get(cacheKey);
833+
834+
if (edgeCache == null) {
835+
throw new RuntimeException(String.format(
836+
"Edge cache not found for graphId %d, edgeTypeId %d",
837+
edgeHeader.getGraphId(), noDirectedTypeId));
838+
}
839+
840+
Map<String, ValueWrapper> props = decodeEdgePropsWithCache(vector, edgeCache, rowIndex);
841+
return new Edge(edgeHeader.getGraphId(),
842+
edgeHeader.getEdgeTypeId(),
843+
edgeHeader.getRank(),
844+
edgeHeader.getSrcId(),
845+
edgeHeader.getDstId(),
846+
props,
847+
graphSchemas);
848+
}
849+
610850

611851
/**
612852
* decode binary to Date

0 commit comments

Comments
 (0)