Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions client/trino-cli/src/main/java/io/trino/cli/StatusPrinter.java
Original file line number Diff line number Diff line change
Expand Up @@ -324,10 +324,14 @@ private void printQueryInfo(QueryStatusInfo results, WarningsPrinter warningsPri
int progressWidth = (min(terminalWidth, 100) - 75) + 17; // progress bar is 17-42 characters wide

if (stats.isScheduled()) {
String progressBar = formatProgressBar(progressWidth,
stats.getCompletedSplits(),
max(0, stats.getRunningSplits()),
stats.getTotalSplits());
int completed = stats.getCompletedSplits();
int running = stats.getRunningSplits();
int total = stats.getTotalSplits();
if (progressPercentage > 0) {
Comment thread
linzebing marked this conversation as resolved.
Outdated
// prevent progress bar from going back and forth for fault tolerant execution
total = max(total, (completed * 100 + progressPercentage - 1) / progressPercentage);
}
String progressBar = formatProgressBar(progressWidth, completed, running, total);

// 0:17 [ 103MB, 802K rows] [5.74MB/s, 44.9K rows/s] [=====>> ] 10%
String progressLine = format("%s [%5s rows, %6s] [%5s rows/s, %8s] [%s] %d%%",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;

import java.util.ArrayDeque;
import java.util.OptionalDouble;
import java.util.Queue;

import static com.google.common.base.MoreObjects.toStringHelper;
import static java.lang.Math.min;
Expand Down Expand Up @@ -197,7 +199,33 @@ public OptionalDouble getProgressPercentage()
if (!scheduled || totalSplits == 0) {
return OptionalDouble.empty();
}
return OptionalDouble.of(min(100, (completedSplits * 100.0) / totalSplits));

double percentageSum = 0.0;
int scheduledStages = 0;
int totalStages = 0;
Queue<StageStats> queue = new ArrayDeque<>();
queue.add(rootStage);
while (!queue.isEmpty()) {
StageStats stage = queue.poll();
totalStages++;
if (stage.isDone() || stage.getState().equals("PENDING") || stage.getState().equals("RUNNING")) {
percentageSum += 100.0 * stage.getCompletedSplits() / stage.getTotalSplits();
scheduledStages++;
}
queue.addAll(stage.getSubStages());
}
if (scheduledStages == totalStages) {
return OptionalDouble.of(min(100, (completedSplits * 100.0) / totalSplits));
}
else {
// Unlike pipelined execution, fault tolerant execution doesn't execute stages all at
// once and some stages will be in PLANNED state in the middle of execution. Therefore,
// we don't know the number of total splits upfront.
//
// To avoid the confusion of progress bar going back and forth, we calculate the
// progress percentage of each stage (0 if not scheduled), and average them.
return OptionalDouble.of(min(100, percentageSum / totalStages));
}
}

@JsonProperty
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -618,7 +618,7 @@ private QueryStats getQueryStats(Optional<StageInfo> rootStage, List<StageInfo>

boolean isScheduled = rootStage.isPresent() && allStages.stream()
.map(StageInfo::getState)
.allMatch(state -> state == StageState.RUNNING || state == StageState.PENDING || state.isDone());
.anyMatch(state -> state == StageState.RUNNING || state == StageState.PENDING || state.isDone());
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how does it impact progress bar rendering for non-fault tolerant execution? Does it impact anything else than progress bar rendering?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked all text occurrences of isScheduled, seems it's only used in progress bar rendering

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would recommend to refrain from changing the isScheduled semantics. If it's only used for progress bar rendering can we implement a check that we need there? (or maybe add a separate boolean filed, isAnyStageScheduled)?

Copy link
Copy Markdown
Member Author

@linzebing linzebing May 9, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would argue that anyMatch is the right semantics here. As long as any of the stage is scheduled, then the whole query should be seen as scheduled, right?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For a single stage the SCHEDULED status indicates that all splits have been scheduled. That's why I'm a little worried that it might be not intuitive for isScheduled to return true as soon as only a single stage has all it's split scheduled.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then for fault tolerant execution, it's not scheduled until the last stage executes, which doesn't make sense. Plus, isScheduled is only used in progress bar, so if we add a isAnyStageScheduled, then will leave isScheduled effectively useless (and therefore should be removed).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think we can simply rename it?


return new QueryStats(
queryStateTimer.getCreateTime(),
Expand Down