@@ -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