MCPcopy Create free account
hub / github.com/apache/impala / ProcessBuildInputAndOpenProbe

Method ProcessBuildInputAndOpenProbe

be/src/exec/blocking-join-node.cc:236–323  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

234}
235
236Status BlockingJoinNode::ProcessBuildInputAndOpenProbe(
237 RuntimeState* state, JoinBuilder* build_sink) {
238 // This function implements various strategies for executing Open() on the left child
239 // and doing or waiting for the join build. Some allow the two to proceed in parallel,
240 // while others do them serially. Generally parallelism yields better performance
241 // except inside a subplan. There we expect Open() to be called a number of times
242 // proportional to the input data of the SubplanNode, so processing the build input
243 // in the main thread can be more efficient, assuming that thread creation is expensive
244 // relative to a single subplan iteration.
245 //
246 // In this block, we also compute the 'overlap' time for the left and right child. This
247 // is the time (i.e. clock reads) when the right child stops overlapping with the left
248 // child. For the single threaded case, the left and right child never overlap. For the
249 // build side in a different thread, the overlap stops when the left child Open()
250 // returns.
251 if (UseSeparateBuild(state->query_options())) {
252 // Open the left child in parallel before waiting for the build fragment to maximise
253 // parallelism. The build execution is done concurrently by the build finstance's
254 // thread.
255 RETURN_IF_ERROR(child(0)->Open(state));
256 // AcquireResourcesForBuild() opens the buffer pool client, so that probe reservation
257 // can be transferred.
258 RETURN_IF_ERROR(AcquireResourcesForBuild(state));
259 {
260 SCOPED_TIMER(runtime_profile_->inactive_timer());
261 events_->MarkEvent("Waiting for initial build");
262 RETURN_IF_ERROR(build_sink->WaitForInitialBuild(state));
263 events_->MarkEvent("Initial build available");
264 }
265 waited_for_build_ = true;
266 } else if (!IsInSubplan() && state->resource_pool()->TryAcquireThreadToken()) {
267 // The build is integrated into the join node and we got a thread token. Do the hash
268 // table build in a separate thread.
269 Status build_side_status;
270 runtime_profile()->AppendExecOption("Join Build-Side Prepared Asynchronously");
271 string thread_name = Substitute("join-build-thread (finst:$0, plan-node-id:$1)",
272 PrintId(state->fragment_instance_id()), id());
273 unique_ptr<Thread> build_thread;
274 Status thread_status = Thread::Create(FragmentInstanceState::FINST_THREAD_GROUP_NAME,
275 thread_name, [this, state, build_sink, status=&build_side_status]() {
276 ProcessBuildInputAsync(state, build_sink, status);
277 }, &build_thread, true);
278 if (!thread_status.ok()) {
279 state->resource_pool()->ReleaseThreadToken(false);
280 return thread_status;
281 }
282 // Open the left child so that it may perform any initialisation in parallel.
283 // Don't exit even if we see an error, we still need to wait for the build thread
284 // to finish.
285 Status open_status = child(0)->Open(state);
286
287 // The left/right child overlap stops here.
288 built_probe_overlap_stop_watch_.SetTimeCeiling();
289
290 // Blocks until ProcessBuildInput has returned, after which the build side structures
291 // are fully constructed.
292 build_thread->Join();
293 RETURN_IF_ERROR(build_side_status);

Callers

nothing calls this directly

Calls 15

SubstituteFunction · 0.85
PrintIdFunction · 0.85
CreateClass · 0.85
OKFunction · 0.85
inactive_timerMethod · 0.80
MarkEventMethod · 0.80
WaitForInitialBuildMethod · 0.80
TryAcquireThreadTokenMethod · 0.80
resource_poolMethod · 0.80
AppendExecOptionMethod · 0.80
resetMethod · 0.65
OpenMethod · 0.45

Tested by

no test coverage detected