Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show time elapsed for all tasks and use Duration for the duration and eta. #1771

Merged
merged 3 commits into from
Sep 27, 2024
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import se.llbit.util.ProgressListener;

import java.text.DecimalFormat;
import java.time.Duration;

/**
* Prints progress to standard out.
Expand All @@ -35,16 +36,17 @@ public ConsoleProgressListener() {
decimalFormat.setGroupingUsed(true);
}

@Override public void setProgress(String task, int done, int start, int target) {
@Override public void setProgress(String task, int done, int start, int target, Duration elapsedTime) {
String line = String.format("%s: %.1f%% (%s of %s)", task, 100 * done / (float) target,
decimalFormat.format(done), decimalFormat.format(target));
output(line, done == target);
}

@Override public void setProgress(String task, int done, int start, int target, String eta) {
@Override public void setProgress(String task, int done, int start, int target, Duration elapsedTime, Duration remainingTime) {
output(String.format("%s: %.1f%% (%s of %s) [ETA=%s]",
task, 100 * done / (float) target,
decimalFormat.format(done), decimalFormat.format(target), eta),
decimalFormat.format(done), decimalFormat.format(target),
String.format("%d:%02d:%02d", remainingTime.toHours(), remainingTime.toMinutesPart(), remainingTime.toSecondsPart())),
done == target);
}

Expand Down
15 changes: 5 additions & 10 deletions chunky/src/java/se/llbit/chunky/renderer/DefaultRenderManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import se.llbit.math.ColorUtil;
import se.llbit.util.TaskTracker;

import java.time.Duration;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.BooleanSupplier;
Expand Down Expand Up @@ -385,19 +386,13 @@ private int samplesPerSecond() {
}

private void updateRenderProgress() {
double renderTime = bufferedScene.renderTime / 1000.0;

// Notify progress listener.
int target = bufferedScene.getTargetSpp();
long etaSeconds = (long) (((target - bufferedScene.spp) * renderTime) / bufferedScene.spp);
if (etaSeconds > 0) {
int seconds = (int) ((etaSeconds) % 60);
int minutes = (int) ((etaSeconds / 60) % 60);
int hours = (int) (etaSeconds / 3600);
String eta = String.format("%d:%02d:%02d", hours, minutes, seconds);
renderTask.update("Rendering", target, bufferedScene.spp, eta);
long etaMillis = (long) (((target - bufferedScene.spp) * bufferedScene.renderTime) / bufferedScene.spp);
if (etaMillis > 0) {
renderTask.update("Rendering", target, bufferedScene.spp, Duration.ofMillis(etaMillis));
} else {
renderTask.update("Rendering", target, bufferedScene.spp, "");
renderTask.update("Rendering", target, bufferedScene.spp);
}

synchronized (this) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public String getDescription() {
@Override
public void render(DefaultRenderManager manager) throws InterruptedException {
TaskTracker.Task task = manager.getRenderTask();
task.update("Preparing preview", 2, 0, "");
task.update("Preparing preview", 2, 0);

Scene scene = manager.bufferedScene;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.net.URL;
import java.nio.file.Path;
import java.text.DecimalFormat;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Collection;
import java.util.IdentityHashMap;
Expand Down Expand Up @@ -63,7 +64,6 @@
import se.llbit.chunky.map.WorldMapLoader;
import se.llbit.chunky.renderer.*;
import se.llbit.chunky.renderer.export.PictureExportFormats;
import se.llbit.chunky.renderer.RenderManager;
import se.llbit.chunky.renderer.export.PictureExportFormat;
import se.llbit.chunky.ui.ChunkMap;
import se.llbit.chunky.ui.dialogs.*;
Expand All @@ -73,7 +73,6 @@
import se.llbit.chunky.ui.ProgressTracker;
import se.llbit.chunky.ui.RenderCanvasFx;
import se.llbit.chunky.ui.UILogReceiver;
import se.llbit.chunky.ui.dialogs.WorldChooser;
import se.llbit.chunky.renderer.scene.*;
import se.llbit.chunky.world.ChunkSelectionTracker;
import se.llbit.chunky.world.ChunkView;
Expand Down Expand Up @@ -160,7 +159,7 @@ public class ChunkyFxController
}

private final ProgressListener progressListener = new ProgressListener() {
@Override public void setProgress(String task, int done, int start, int target) {
@Override public void setProgress(String task, int done, int start, int target, Duration elapsedTime) {
Platform.runLater(() -> {
progressBar.setProgress((double) done / (target - start));
if (target - start > 0) {
Expand All @@ -171,10 +170,11 @@ public class ChunkyFxController
progressLbl.setTooltip(null);
}
etaLbl.setText("ETA: N/A");
renderTimeLbl.setText(String.format("Time: %d:%02d:%02d", elapsedTime.toHours(), elapsedTime.toMinutesPart(), elapsedTime.toSecondsPart()));
});
}

@Override public void setProgress(String task, int done, int start, int target, String eta) {
@Override public void setProgress(String task, int done, int start, int target, Duration elapsedTime, Duration remainingTime) {
Platform.runLater(() -> {
progressBar.setProgress((double) done / (target - start));
if (target - start > 0) {
Expand All @@ -184,7 +184,8 @@ public class ChunkyFxController
progressLbl.setText(String.format("%s", task));
progressLbl.setTooltip(null);
}
etaLbl.setText("ETA: " + eta);
etaLbl.setText(String.format("ETA: %d:%02d:%02d", remainingTime.toHours(), remainingTime.toMinutesPart(), remainingTime.toSecondsPart()));
renderTimeLbl.setText(String.format("Time: %d:%02d:%02d", elapsedTime.toHours(), elapsedTime.toMinutesPart(), elapsedTime.toSecondsPart()));
});
}
};
Expand Down
10 changes: 6 additions & 4 deletions chunky/src/java/se/llbit/util/ProgressListener.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,25 @@
*/
package se.llbit.util;

import java.time.Duration;

/**
* Progress listener.
*
* @author Jesper Öqvist <[email protected]>
*/
public interface ProgressListener {
ProgressListener NONE = (task, done, start, target) -> {};
ProgressListener NONE = (task, done, start, target, duration) -> {};

/**
* Update progress without ETA.
*/
void setProgress(String task, int done, int start, int target);
void setProgress(String task, int done, int start, int target, Duration elapsedTime);

/**
* Update progress with ETA.
*/
default void setProgress(String task, int done, int start, int target, String eta) {
setProgress(task, done, start, target);
default void setProgress(String task, int done, int start, int target, Duration elapsedTime, Duration remainingTime) {
setProgress(task, done, start, target, elapsedTime);
}
}
93 changes: 60 additions & 33 deletions chunky/src/java/se/llbit/util/TaskTracker.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@

import se.llbit.log.Log;

import java.time.Duration;
import java.util.Optional;

/**
* A task tracker is used to update a progress listener with current task progress.
* The task tracker has a stack of tasks. When a new task is created the previous
Expand Down Expand Up @@ -57,7 +60,7 @@ public TaskTracker(ProgressListener progress, TaskBuilder taskBuilder) {
}

public TaskTracker(ProgressListener progress, TaskBuilder taskBuilder,
TaskBuilder backgroundTaskBuilder) {
TaskBuilder backgroundTaskBuilder) {
this.progress = progress;
this.taskBuilder = taskBuilder;
this.backgroundTask = backgroundTaskBuilder.newTask(this, null, "N/A", 1);
Expand All @@ -66,17 +69,25 @@ public TaskTracker(ProgressListener progress, TaskBuilder taskBuilder,

public static class Task implements AutoCloseable {
public static final Task NONE = new Task(null, null, "None", 1) {
@Override protected void update() { }
@Override protected void updateEta() { }
@Override public void close() { }
@Override
protected void update() {
}

@Override
protected void updateEta() {
}

@Override
public void close() {
}
};

private String taskName;
private int target;
private int done;
protected final TaskTracker tracker;
protected final Task previous;
private String eta = "";
private Optional<Duration> eta = Optional.empty();
protected long startTime;

public Task(TaskTracker tracker, Task previous, String taskName, int size) {
Expand All @@ -88,85 +99,101 @@ public Task(TaskTracker tracker, Task previous, String taskName, int size) {
this.startTime = System.currentTimeMillis();
}

@Override public void close() {
@Override
public void close() {
tracker.currentTask = previous;
previous.update();
Log.infof("Task %s: %d in %.3f seconds", taskName, done,
(System.currentTimeMillis() - startTime) / 1000.0);
}

protected void update() {
tracker.updateProgress(taskName, target, done, eta);
eta.ifPresentOrElse(
eta -> tracker.updateProgress(taskName, target, done, Duration.ofMillis(System.currentTimeMillis() - startTime), eta),
() -> tracker.updateProgress(taskName, target, done, Duration.ofMillis(System.currentTimeMillis() - startTime)));
}

/** Change the task name. */
/**
* Change the task name.
*/
public void update(String task) {
this.taskName = task;
update();
}

/** Set the current progress. */
/**
* Set the current progress.
*/
public void update(int done) {
this.done = done;
update();
}

/** Set the current progress. */
/**
* Set the current progress.
*/
public void update(int target, int done) {
this.done = done;
this.target = target;
update();
}

/** Changes the task name and state. */
/**
* Changes the task name and state.
*/
public void update(String task, int target, int done) {
update(task, target, done, "");
update(task, target, done, null);
}

/** Changes the task name and state. */
public void update(String task, int target, int done, String eta) {
/**
* Changes the task name and state.
*/
public void update(String task, int target, int done, Duration eta) {
this.taskName = task;
this.done = done;
this.target = target;
this.eta = eta;
this.eta = Optional.ofNullable(eta);
update();
}

protected void updateEta() {
long etaSeconds = 0;
if (done > 0) {
if (done > 0 && done <= target) {
etaSeconds = ((target - done) * (System.currentTimeMillis() - startTime) / 1000) / done;
}
if (etaSeconds > 0) {
int seconds = (int) ((etaSeconds) % 60);
int minutes = (int) ((etaSeconds / 60) % 60);
int hours = (int) (etaSeconds / 3600);
eta = String.format("%d:%02d:%02d", hours, minutes, seconds);
eta = Optional.of(Duration.ofSeconds(etaSeconds));
} else {
eta = "N/A";
eta = Optional.empty();
}
update();
}

/** Set the current progress and calculate an ETA. */
/**
* Set the current progress and calculate an ETA.
*/
public void updateEta(int done) {
this.done = done;
updateEta();
}

/** Set the current progress and calculate an ETA. */
/**
* Set the current progress and calculate an ETA.
*/
public void updateEta(int target, int done) {
this.done = done;
this.target = target;
updateEta();
}

/** Reset the ETA start time. */
/**
* Reset the ETA start time.
*/
public void updateStartTime() {
this.startTime = System.currentTimeMillis();
}

/** Ratelimited update. Only update when the new progress is greater than the old progress + {@code interval} */
/**
* Ratelimited update. Only update when the new progress is greater than the old progress + {@code interval}
*/
public void updateInterval(int target, int done, int interval) {
if (target != this.target || done > this.done + interval) {
this.updateEta(target, done);
Expand All @@ -180,12 +207,12 @@ public void updateInterval(int done, int interval) {
}
}

private void updateProgress(String taskName, int target, int done, String eta) {
if (!eta.isEmpty()) {
progress.setProgress(taskName, done, 0, target, eta);
} else {
progress.setProgress(taskName, done, 0, target);
}
private void updateProgress(String taskName, int target, int done, Duration duration, Duration eta) {
progress.setProgress(taskName, done, 0, target, duration, eta);
}

private void updateProgress(String taskName, int target, int done, Duration duration) {
progress.setProgress(taskName, done, 0, target, duration);
}

public final Task task(String taskName) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.time.Duration;
import java.util.Arrays;
import java.util.Base64;
import java.util.HashMap;
Expand Down Expand Up @@ -70,7 +71,7 @@ public void init() {
final Map<String, Integer> previousProgress = new HashMap<>();

@Override
public void setProgress(String task, int done, int start, int target) {
public void setProgress(String task, int done, int start, int target, Duration elapsedTime) {
int previous = previousProgress.getOrDefault(task, Integer.MIN_VALUE);
// check that progress is monotonically increasing
assertTrue(done >= previous, "progress (" + done + ") should be greater or equal to previous progress (" + previous + ")");
Expand Down