Skip to content

Commit e739cdf

Browse files
authored
fix(interactive): Optimize the edge expand and path expand operator when there are many vertex labels (#4569)
Fixes
1 parent a10bcd2 commit e739cdf

File tree

2 files changed

+173
-118
lines changed

2 files changed

+173
-118
lines changed

flex/engines/graph_db/runtime/common/operators/retrieve/edge_expand.cc

Lines changed: 33 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -352,9 +352,14 @@ bl::result<Context> EdgeExpand::expand_edge_without_predicate(
352352
get_expand_label_set(graph, label_set, params.labels, params.dir);
353353
std::vector<std::pair<LabelTriplet, PropertyType>> label_props;
354354
std::vector<std::vector<PropertyType>> props_vec;
355-
for (auto& triplet : labels) {
355+
std::vector<std::vector<LabelTriplet>> in_labels_map(
356+
graph.schema().vertex_label_num()),
357+
out_labels_map(graph.schema().vertex_label_num());
358+
for (const auto& triplet : labels) {
356359
auto& props = graph.schema().get_edge_properties(
357360
triplet.src_label, triplet.dst_label, triplet.edge_label);
361+
in_labels_map[triplet.dst_label].emplace_back(triplet);
362+
out_labels_map[triplet.src_label].emplace_back(triplet);
358363
PropertyType pt = PropertyType::kEmpty;
359364
if (!props.empty()) {
360365
pt = props[0];
@@ -416,11 +421,9 @@ bl::result<Context> EdgeExpand::expand_edge_without_predicate(
416421

417422
auto builder = SDMLEdgeColumnBuilder::builder(params.dir, label_props);
418423
if (params.dir == Direction::kOut) {
419-
foreach_vertex(input_vertex_list, [&](size_t index, label_t label,
420-
vid_t v) {
421-
for (auto& triplet : labels) {
422-
if (triplet.src_label == label) {
423-
if (params.dir == Direction::kOut) {
424+
foreach_vertex(
425+
input_vertex_list, [&](size_t index, label_t label, vid_t v) {
426+
for (const auto& triplet : out_labels_map[label]) {
424427
auto oe_iter = graph.GetOutEdgeIterator(
425428
label, v, triplet.dst_label, triplet.edge_label);
426429
while (oe_iter.IsValid()) {
@@ -430,15 +433,11 @@ bl::result<Context> EdgeExpand::expand_edge_without_predicate(
430433
oe_iter.Next();
431434
}
432435
}
433-
}
434-
}
435-
});
436+
});
436437
} else {
437-
foreach_vertex(input_vertex_list, [&](size_t index, label_t label,
438-
vid_t v) {
439-
for (auto& triplet : labels) {
440-
if (triplet.dst_label == label) {
441-
if (params.dir == Direction::kIn) {
438+
foreach_vertex(
439+
input_vertex_list, [&](size_t index, label_t label, vid_t v) {
440+
for (const auto& triplet : in_labels_map[label]) {
442441
auto ie_iter = graph.GetInEdgeIterator(
443442
label, v, triplet.src_label, triplet.edge_label);
444443
while (ie_iter.IsValid()) {
@@ -448,9 +447,7 @@ bl::result<Context> EdgeExpand::expand_edge_without_predicate(
448447
ie_iter.Next();
449448
}
450449
}
451-
}
452-
}
453-
});
450+
});
454451
}
455452

456453
ctx.set_with_reshuffle(params.alias, builder.finish(nullptr),
@@ -495,28 +492,26 @@ bl::result<Context> EdgeExpand::expand_edge_without_predicate(
495492
*std::dynamic_pointer_cast<IVertexColumn>(ctx.get(params.v_tag));
496493
foreach_vertex(
497494
input_vertex_list, [&](size_t index, label_t label, vid_t v) {
498-
for (auto& triplet : labels) {
499-
if (triplet.src_label == label) {
500-
auto oe_iter = graph.GetOutEdgeIterator(
501-
label, v, triplet.dst_label, triplet.edge_label);
502-
while (oe_iter.IsValid()) {
503-
auto nbr = oe_iter.GetNeighbor();
504-
builder.push_back_opt(triplet, v, nbr, oe_iter.GetData(),
505-
Direction::kOut);
506-
shuffle_offset.push_back(index);
507-
oe_iter.Next();
508-
}
495+
for (const auto& triplet : out_labels_map[label]) {
496+
auto oe_iter = graph.GetOutEdgeIterator(
497+
label, v, triplet.dst_label, triplet.edge_label);
498+
while (oe_iter.IsValid()) {
499+
auto nbr = oe_iter.GetNeighbor();
500+
builder.push_back_opt(triplet, v, nbr, oe_iter.GetData(),
501+
Direction::kOut);
502+
shuffle_offset.push_back(index);
503+
oe_iter.Next();
509504
}
510-
if (triplet.dst_label == label) {
511-
auto ie_iter = graph.GetInEdgeIterator(
512-
label, v, triplet.src_label, triplet.edge_label);
513-
while (ie_iter.IsValid()) {
514-
auto nbr = ie_iter.GetNeighbor();
515-
builder.push_back_opt(triplet, nbr, v, ie_iter.GetData(),
516-
Direction::kIn);
517-
shuffle_offset.push_back(index);
518-
ie_iter.Next();
519-
}
505+
}
506+
for (const auto& triplet : in_labels_map[label]) {
507+
auto ie_iter = graph.GetInEdgeIterator(
508+
label, v, triplet.src_label, triplet.edge_label);
509+
while (ie_iter.IsValid()) {
510+
auto nbr = ie_iter.GetNeighbor();
511+
builder.push_back_opt(triplet, nbr, v, ie_iter.GetData(),
512+
Direction::kIn);
513+
shuffle_offset.push_back(index);
514+
ie_iter.Next();
520515
}
521516
}
522517
});

flex/engines/graph_db/runtime/common/operators/retrieve/path_expand.cc

Lines changed: 140 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,11 @@ bl::result<Context> PathExpand::edge_expand_v(const GraphReadInterface& graph,
4141
auto& input_vertex_list =
4242
*std::dynamic_pointer_cast<IVertexColumn>(ctx.get(params.start_tag));
4343
std::set<label_t> labels;
44-
for (auto& label : params.labels) {
44+
std::vector<std::vector<LabelTriplet>> out_labels_map(
45+
graph.schema().vertex_label_num());
46+
for (const auto& label : params.labels) {
4547
labels.emplace(label.dst_label);
48+
out_labels_map[label.src_label].emplace_back(label);
4649
}
4750

4851
auto builder = MLVertexColumnBuilder::builder(labels);
@@ -71,17 +74,15 @@ bl::result<Context> PathExpand::edge_expand_v(const GraphReadInterface& graph,
7174
auto label = std::get<0>(tuple);
7275
auto v = std::get<1>(tuple);
7376
auto index = std::get<2>(tuple);
74-
for (auto& label_triplet : params.labels) {
75-
if (label_triplet.src_label == label) {
76-
auto oe_iter = graph.GetOutEdgeIterator(
77-
label_triplet.src_label, v, label_triplet.dst_label,
78-
label_triplet.edge_label);
79-
80-
while (oe_iter.IsValid()) {
81-
auto nbr = oe_iter.GetNeighbor();
82-
output.emplace_back(label_triplet.dst_label, nbr, index);
83-
oe_iter.Next();
84-
}
77+
for (const auto& label_triplet : out_labels_map[label]) {
78+
auto oe_iter = graph.GetOutEdgeIterator(label_triplet.src_label, v,
79+
label_triplet.dst_label,
80+
label_triplet.edge_label);
81+
82+
while (oe_iter.IsValid()) {
83+
auto nbr = oe_iter.GetNeighbor();
84+
output.emplace_back(label_triplet.dst_label, nbr, index);
85+
oe_iter.Next();
8586
}
8687
}
8788
}
@@ -90,10 +91,69 @@ bl::result<Context> PathExpand::edge_expand_v(const GraphReadInterface& graph,
9091
ctx.set_with_reshuffle(params.alias, builder.finish(nullptr),
9192
shuffle_offset);
9293
return ctx;
93-
} else if (params.dir == Direction::kBoth) {
94+
} else if (params.dir == Direction::kIn) {
95+
auto& input_vertex_list =
96+
*std::dynamic_pointer_cast<IVertexColumn>(ctx.get(params.start_tag));
9497
std::set<label_t> labels;
98+
std::vector<std::vector<LabelTriplet>> in_labels_map(
99+
graph.schema().vertex_label_num());
95100
for (auto& label : params.labels) {
101+
labels.emplace(label.src_label);
102+
in_labels_map[label.dst_label].emplace_back(label);
103+
}
104+
105+
auto builder = MLVertexColumnBuilder::builder(labels);
106+
std::vector<std::tuple<label_t, vid_t, size_t>> input;
107+
std::vector<std::tuple<label_t, vid_t, size_t>> output;
108+
foreach_vertex(input_vertex_list,
109+
[&](size_t index, label_t label, vid_t v) {
110+
output.emplace_back(label, v, index);
111+
});
112+
int depth = 0;
113+
while (depth < params.hop_upper && (!output.empty())) {
114+
input.clear();
115+
std::swap(input, output);
116+
if (depth >= params.hop_lower) {
117+
for (const auto& tuple : input) {
118+
builder.push_back_vertex({std::get<0>(tuple), std::get<1>(tuple)});
119+
shuffle_offset.push_back(std::get<2>(tuple));
120+
}
121+
}
122+
123+
if (depth + 1 >= params.hop_upper) {
124+
break;
125+
}
126+
127+
for (const auto& tuple : input) {
128+
auto label = std::get<0>(tuple);
129+
auto v = std::get<1>(tuple);
130+
auto index = std::get<2>(tuple);
131+
for (const auto& label_triplet : in_labels_map[label]) {
132+
auto oe_iter = graph.GetInEdgeIterator(label_triplet.dst_label, v,
133+
label_triplet.src_label,
134+
label_triplet.edge_label);
135+
136+
while (oe_iter.IsValid()) {
137+
auto nbr = oe_iter.GetNeighbor();
138+
output.emplace_back(label_triplet.src_label, nbr, index);
139+
oe_iter.Next();
140+
}
141+
}
142+
}
143+
++depth;
144+
}
145+
ctx.set_with_reshuffle(params.alias, builder.finish(nullptr),
146+
shuffle_offset);
147+
return ctx;
148+
} else if (params.dir == Direction::kBoth) {
149+
std::set<label_t> labels;
150+
std::vector<std::vector<LabelTriplet>> in_labels_map(
151+
graph.schema().vertex_label_num()),
152+
out_labels_map(graph.schema().vertex_label_num());
153+
for (const auto& label : params.labels) {
96154
labels.emplace(label.dst_label);
155+
in_labels_map[label.dst_label].emplace_back(label);
156+
out_labels_map[label.src_label].emplace_back(label);
97157
}
98158

99159
auto builder = MLVertexColumnBuilder::builder(labels);
@@ -135,27 +195,25 @@ bl::result<Context> PathExpand::edge_expand_v(const GraphReadInterface& graph,
135195
auto label = std::get<0>(tuple);
136196
auto v = std::get<1>(tuple);
137197
auto index = std::get<2>(tuple);
138-
for (auto& label_triplet : params.labels) {
139-
if (label_triplet.src_label == label) {
140-
auto oe_iter = graph.GetOutEdgeIterator(
141-
label_triplet.src_label, v, label_triplet.dst_label,
142-
label_triplet.edge_label);
143-
144-
while (oe_iter.IsValid()) {
145-
auto nbr = oe_iter.GetNeighbor();
146-
output.emplace_back(label_triplet.dst_label, nbr, index);
147-
oe_iter.Next();
148-
}
198+
for (const auto& label_triplet : out_labels_map[label]) {
199+
auto oe_iter = graph.GetOutEdgeIterator(label_triplet.src_label, v,
200+
label_triplet.dst_label,
201+
label_triplet.edge_label);
202+
203+
while (oe_iter.IsValid()) {
204+
auto nbr = oe_iter.GetNeighbor();
205+
output.emplace_back(label_triplet.dst_label, nbr, index);
206+
oe_iter.Next();
149207
}
150-
if (label_triplet.dst_label == label) {
151-
auto ie_iter = graph.GetInEdgeIterator(label_triplet.dst_label, v,
152-
label_triplet.src_label,
153-
label_triplet.edge_label);
154-
while (ie_iter.IsValid()) {
155-
auto nbr = ie_iter.GetNeighbor();
156-
output.emplace_back(label_triplet.src_label, nbr, index);
157-
ie_iter.Next();
158-
}
208+
}
209+
for (const auto& label_triplet : in_labels_map[label]) {
210+
auto ie_iter = graph.GetInEdgeIterator(label_triplet.dst_label, v,
211+
label_triplet.src_label,
212+
label_triplet.edge_label);
213+
while (ie_iter.IsValid()) {
214+
auto nbr = ie_iter.GetNeighbor();
215+
output.emplace_back(label_triplet.src_label, nbr, index);
216+
ie_iter.Next();
159217
}
160218
}
161219
}
@@ -178,6 +236,13 @@ bl::result<Context> PathExpand::edge_expand_p(const GraphReadInterface& graph,
178236
*std::dynamic_pointer_cast<IVertexColumn>(ctx.get(params.start_tag));
179237
auto label_sets = input_vertex_list.get_labels_set();
180238
auto labels = params.labels;
239+
std::vector<std::vector<LabelTriplet>> out_labels_map(
240+
graph.schema().vertex_label_num()),
241+
in_labels_map(graph.schema().vertex_label_num());
242+
for (const auto& triplet : labels) {
243+
out_labels_map[triplet.src_label].emplace_back(triplet);
244+
in_labels_map[triplet.dst_label].emplace_back(triplet);
245+
}
181246
auto dir = params.dir;
182247
std::vector<std::pair<std::unique_ptr<PathImpl>, size_t>> input;
183248
std::vector<std::pair<std::unique_ptr<PathImpl>, size_t>> output;
@@ -196,18 +261,16 @@ bl::result<Context> PathExpand::edge_expand_p(const GraphReadInterface& graph,
196261
if (depth + 1 < params.hop_upper) {
197262
for (auto& [path, index] : input) {
198263
auto end = path->get_end();
199-
for (auto& label_triplet : labels) {
200-
if (label_triplet.src_label == end.label_) {
201-
auto oe_iter = graph.GetOutEdgeIterator(end.label_, end.vid_,
202-
label_triplet.dst_label,
203-
label_triplet.edge_label);
204-
while (oe_iter.IsValid()) {
205-
std::unique_ptr<PathImpl> new_path = path->expand(
206-
label_triplet.edge_label, label_triplet.dst_label,
207-
oe_iter.GetNeighbor());
208-
output.emplace_back(std::move(new_path), index);
209-
oe_iter.Next();
210-
}
264+
for (const auto& label_triplet : out_labels_map[end.label_]) {
265+
auto oe_iter = graph.GetOutEdgeIterator(end.label_, end.vid_,
266+
label_triplet.dst_label,
267+
label_triplet.edge_label);
268+
while (oe_iter.IsValid()) {
269+
std::unique_ptr<PathImpl> new_path =
270+
path->expand(label_triplet.edge_label,
271+
label_triplet.dst_label, oe_iter.GetNeighbor());
272+
output.emplace_back(std::move(new_path), index);
273+
oe_iter.Next();
211274
}
212275
}
213276
}
@@ -244,18 +307,16 @@ bl::result<Context> PathExpand::edge_expand_p(const GraphReadInterface& graph,
244307
if (depth + 1 < params.hop_upper) {
245308
for (const auto& [path, index] : input) {
246309
auto end = path->get_end();
247-
for (const auto& label_triplet : labels) {
248-
if (label_triplet.dst_label == end.label_) {
249-
auto ie_iter = graph.GetInEdgeIterator(end.label_, end.vid_,
250-
label_triplet.src_label,
251-
label_triplet.edge_label);
252-
while (ie_iter.IsValid()) {
253-
std::unique_ptr<PathImpl> new_path = path->expand(
254-
label_triplet.edge_label, label_triplet.src_label,
255-
ie_iter.GetNeighbor());
256-
output.emplace_back(std::move(new_path), index);
257-
ie_iter.Next();
258-
}
310+
for (const auto& label_triplet : in_labels_map[end.label_]) {
311+
auto ie_iter = graph.GetInEdgeIterator(end.label_, end.vid_,
312+
label_triplet.src_label,
313+
label_triplet.edge_label);
314+
while (ie_iter.IsValid()) {
315+
std::unique_ptr<PathImpl> new_path =
316+
path->expand(label_triplet.edge_label,
317+
label_triplet.src_label, ie_iter.GetNeighbor());
318+
output.emplace_back(std::move(new_path), index);
319+
ie_iter.Next();
259320
}
260321
}
261322
}
@@ -292,30 +353,29 @@ bl::result<Context> PathExpand::edge_expand_p(const GraphReadInterface& graph,
292353
if (depth + 1 < params.hop_upper) {
293354
for (auto& [path, index] : input) {
294355
auto end = path->get_end();
295-
for (auto& label_triplet : labels) {
296-
if (label_triplet.src_label == end.label_) {
297-
auto oe_iter = graph.GetOutEdgeIterator(end.label_, end.vid_,
298-
label_triplet.dst_label,
299-
label_triplet.edge_label);
300-
while (oe_iter.IsValid()) {
301-
auto new_path = path->expand(label_triplet.edge_label,
302-
label_triplet.dst_label,
303-
oe_iter.GetNeighbor());
304-
output.emplace_back(std::move(new_path), index);
305-
oe_iter.Next();
306-
}
356+
for (const auto& label_triplet : out_labels_map[end.label_]) {
357+
auto oe_iter = graph.GetOutEdgeIterator(end.label_, end.vid_,
358+
label_triplet.dst_label,
359+
label_triplet.edge_label);
360+
while (oe_iter.IsValid()) {
361+
auto new_path =
362+
path->expand(label_triplet.edge_label,
363+
label_triplet.dst_label, oe_iter.GetNeighbor());
364+
output.emplace_back(std::move(new_path), index);
365+
oe_iter.Next();
307366
}
308-
if (label_triplet.dst_label == end.label_) {
309-
auto ie_iter = graph.GetInEdgeIterator(end.label_, end.vid_,
310-
label_triplet.src_label,
311-
label_triplet.edge_label);
312-
while (ie_iter.IsValid()) {
313-
auto new_path = path->expand(label_triplet.edge_label,
314-
label_triplet.src_label,
315-
ie_iter.GetNeighbor());
316-
output.emplace_back(std::move(new_path), index);
317-
ie_iter.Next();
318-
}
367+
}
368+
369+
for (const auto& label_triplet : in_labels_map[end.label_]) {
370+
auto ie_iter = graph.GetInEdgeIterator(end.label_, end.vid_,
371+
label_triplet.src_label,
372+
label_triplet.edge_label);
373+
while (ie_iter.IsValid()) {
374+
auto new_path =
375+
path->expand(label_triplet.edge_label,
376+
label_triplet.src_label, ie_iter.GetNeighbor());
377+
output.emplace_back(std::move(new_path), index);
378+
ie_iter.Next();
319379
}
320380
}
321381
}

0 commit comments

Comments
 (0)