progressbar icon indicating copy to clipboard operation
progressbar copied to clipboard

Multiple progress bars end up on a single line under osx with 0.9.4

Open spinscale opened this issue 2 years ago • 6 comments

I am creating multiple progress bars, each one as a task in a thread pool (up to 300). When. the thread pool is running more than one task at once, the progress bars all end up on the same line.

I checked an Terminal.cursorMovementSupported is set to true.

The code looks like this:

executorService.submit(() -> {
    try (CliProgressMonitor progressMonitor = new CliProgressMonitor(message, terminalWidth.get())) {
        // do long running task
    }
});


private static final class CliProgressMonitor extends BatchingProgressMonitor implements AutoCloseable {

    private final ProgressBar progressBar;

    public CliProgressMonitor(String message, int terminalWidth) {
        this.progressBar = new ProgressBarBuilder()
            .setStyle(ProgressBarStyle.UNICODE_BLOCK)
            .setTaskName(message)
            .setMaxRenderedLength(terminalWidth)
            .hideETA()
            .build();
    }

    ...
}

Is there anything wrong with the approach, should the closing of the progressbar be changed or sth?

Thanks for your help!

spinscale avatar Sep 23 '22 08:09 spinscale

Which environment are you running in? e.g. Linux terminal, or Windows WSL, or in a Docker container?

ctongfei avatar Oct 10 '22 03:10 ctongfei

Under osx, I tried with iterm2 as well as wezTerm. This is what it looks like..

2022-10-10 14 44 12

So, every "Fetching repo..." is an own progressbar (that is the message), and if you look closely, the last line flips between the 10 concurrent running progresses and only creates a newline once the progress is finished.

spinscale avatar Oct 10 '22 12:10 spinscale

I am creating multiple progress bars, each one as a task in a thread pool (up to 300). When. the thread pool is running more than one task at once, the progress bars all end up on the same line.

I checked an Terminal.cursorMovementSupported is set to true.

The code looks like this:

executorService.submit(() -> {
    try (CliProgressMonitor progressMonitor = new CliProgressMonitor(message, terminalWidth.get())) {
        // do long running task
    }
});


private static final class CliProgressMonitor extends BatchingProgressMonitor implements AutoCloseable {

    private final ProgressBar progressBar;

    public CliProgressMonitor(String message, int terminalWidth) {
        this.progressBar = new ProgressBarBuilder()
            .setStyle(ProgressBarStyle.UNICODE_BLOCK)
            .setTaskName(message)
            .setMaxRenderedLength(terminalWidth)
            .hideETA()
            .build();
    }

    ...
}

Is there anything wrong with the approach, should the closing of the progressbar be changed or sth?

Thanks for your help!

maybe you can try this

/**
     * 支持在控制台打印多行进度条
     *
     * @author LCTR
     * @date 2023-05-07
     */
    public class ConsoleMultiProgressBarConsumer
            extends ConsoleProgressBarConsumer {
        final int index;
        final PrintStream out;

        public ConsoleMultiProgressBarConsumer(PrintStream out,
                                               int index) {
            super(out);
            this.out = out;
            this.index = index;
        }

        public ConsoleMultiProgressBarConsumer(PrintStream out,
                                               int maxRenderedLength,
                                               int index) {
            super(out,
                  maxRenderedLength);
            this.out = out;
            this.index = index;
        }

        @Override
        public void accept(String str) {
            out.print(StringExtension.newString("\r\n",
                                                index));

            out.print(matcher.appendTail(sb));
            //super.accept(str);

            out.print(StringExtension.newString("\033[F",
                                                index));
        }
    }
new ProgressBarBuilder()
                                .setTaskName("#01"))
                                .setInitialMax(100)
                                .setConsumer(new ConsoleMultiProgressBarConsumer(new PrintStream(new FileOutputStream(FileDescriptor.out)),
                                                                                 1))
                                .hideEta()
                                .setUpdateIntervalMillis(100)
                                .build();
new ProgressBarBuilder()
                                .setTaskName("#02"))
                                .setInitialMax(100)
                                .setConsumer(new ConsoleMultiProgressBarConsumer(new PrintStream(new FileOutputStream(FileDescriptor.out)),
                                                                                 2))
                                .hideEta()
                                .setUpdateIntervalMillis(100)
                                .build();
new ProgressBarBuilder()
                                .setTaskName("#03"))
                                .setInitialMax(100)
                                .setConsumer(new ConsoleMultiProgressBarConsumer(new PrintStream(new FileOutputStream(FileDescriptor.out)),
                                                                                 3))
                                .hideEta()
                                .setUpdateIntervalMillis(100)
                                .build();

Lc3586 avatar May 07 '23 07:05 Lc3586

I am creating multiple progress bars, each one as a task in a thread pool (up to 300). When. the thread pool is running more than one task at once, the progress bars all end up on the same line. I checked an Terminal.cursorMovementSupported is set to true. The code looks like this:

executorService.submit(() -> {
    try (CliProgressMonitor progressMonitor = new CliProgressMonitor(message, terminalWidth.get())) {
        // do long running task
    }
});


private static final class CliProgressMonitor extends BatchingProgressMonitor implements AutoCloseable {

    private final ProgressBar progressBar;

    public CliProgressMonitor(String message, int terminalWidth) {
        this.progressBar = new ProgressBarBuilder()
            .setStyle(ProgressBarStyle.UNICODE_BLOCK)
            .setTaskName(message)
            .setMaxRenderedLength(terminalWidth)
            .hideETA()
            .build();
    }

    ...
}

Is there anything wrong with the approach, should the closing of the progressbar be changed or sth? Thanks for your help!

maybe you can try this

/**
     * 支持在控制台打印多行进度条
     *
     * @author LCTR
     * @date 2023-05-07
     */
    public class ConsoleMultiProgressBarConsumer
            extends ConsoleProgressBarConsumer {
        final int index;
        final PrintStream out;

        public ConsoleMultiProgressBarConsumer(PrintStream out,
                                               int index) {
            super(out);
            this.out = out;
            this.index = index;
        }

        public ConsoleMultiProgressBarConsumer(PrintStream out,
                                               int maxRenderedLength,
                                               int index) {
            super(out,
                  maxRenderedLength);
            this.out = out;
            this.index = index;
        }

        @Override
        public void accept(String str) {
            out.print(StringExtension.newString("\r\n",
                                                index));

            out.print(matcher.appendTail(sb));
            //super.accept(str);

            out.print(StringExtension.newString("\033[F",
                                                index));
        }
    }
new ProgressBarBuilder()
                                .setTaskName("#01"))
                                .setInitialMax(100)
                                .setConsumer(new ConsoleMultiProgressBarConsumer(new PrintStream(new FileOutputStream(FileDescriptor.out)),
                                                                                 1))
                                .hideEta()
                                .setUpdateIntervalMillis(100)
                                .build();
new ProgressBarBuilder()
                                .setTaskName("#02"))
                                .setInitialMax(100)
                                .setConsumer(new ConsoleMultiProgressBarConsumer(new PrintStream(new FileOutputStream(FileDescriptor.out)),
                                                                                 2))
                                .hideEta()
                                .setUpdateIntervalMillis(100)
                                .build();
new ProgressBarBuilder()
                                .setTaskName("#03"))
                                .setInitialMax(100)
                                .setConsumer(new ConsoleMultiProgressBarConsumer(new PrintStream(new FileOutputStream(FileDescriptor.out)),
                                                                                 3))
                                .hideEta()
                                .setUpdateIntervalMillis(100)
                                .build();

i dont really understand this, where are the matcher and sb in the accept method coming from?

IvanEOD avatar Aug 12 '23 18:08 IvanEOD

/**
 * @author Cool_Loong
 */
public class ConsoleMultiProgressBarConsumer extends ConsoleProgressBarConsumer {
    final PrintStream out;
    final boolean first;

    public ConsoleMultiProgressBarConsumer(PrintStream out, boolean isFirst) {
        super(out);
        this.out = out;
        this.first = isFirst;
    }

    public ConsoleMultiProgressBarConsumer(PrintStream out, int maxRenderedLength, boolean isFirst) {
        super(out, maxRenderedLength);
        this.out = out;
        this.first = isFirst;
    }

    @Override
    public void accept(String str) {
        if (first) {
            out.print('\n');
            out.print("-".repeat(this.getMaxRenderedLength()));
        }
        out.print("\r\n");
        super.accept(str);
    }
}
FIRST = new AtomicBoolean(true);

ProgressBar pb = progressBarBuilder.setTaskName("region " + srcRegion.getRegionX() + "," + srcRegion.getRegionZ())
                .setInitialMax(1024)
                .setStyle(ProgressBarStyle.ASCII)
                .setConsumer(new ConsoleMultiProgressBarConsumer(System.out, FIRST.getAndSet(false)))
                .build()

Displaying multiple lines by a “line feed” character.

CoolLoong avatar Aug 16 '23 14:08 CoolLoong

I am creating multiple progress bars, each one as a task in a thread pool (up to 300). When. the thread pool is running more than one task at once, the progress bars all end up on the same line. I checked an Terminal.cursorMovementSupported is set to true. The code looks like this:

executorService.submit(() -> {
    try (CliProgressMonitor progressMonitor = new CliProgressMonitor(message, terminalWidth.get())) {
        // do long running task
    }
});


private static final class CliProgressMonitor extends BatchingProgressMonitor implements AutoCloseable {

    private final ProgressBar progressBar;

    public CliProgressMonitor(String message, int terminalWidth) {
        this.progressBar = new ProgressBarBuilder()
            .setStyle(ProgressBarStyle.UNICODE_BLOCK)
            .setTaskName(message)
            .setMaxRenderedLength(terminalWidth)
            .hideETA()
            .build();
    }

    ...
}

Is there anything wrong with the approach, should the closing of the progressbar be changed or sth? Thanks for your help!

maybe you can try this

/**
     * 支持在控制台打印多行进度条
     *
     * @author LCTR
     * @date 2023-05-07
     */
    public class ConsoleMultiProgressBarConsumer
            extends ConsoleProgressBarConsumer {
        final int index;
        final PrintStream out;

        public ConsoleMultiProgressBarConsumer(PrintStream out,
                                               int index) {
            super(out);
            this.out = out;
            this.index = index;
        }

        public ConsoleMultiProgressBarConsumer(PrintStream out,
                                               int maxRenderedLength,
                                               int index) {
            super(out,
                  maxRenderedLength);
            this.out = out;
            this.index = index;
        }

        @Override
        public void accept(String str) {
            out.print(StringExtension.newString("\r\n",
                                                index));

            out.print(matcher.appendTail(sb));
            //super.accept(str);

            out.print(StringExtension.newString("\033[F",
                                                index));
        }
    }
new ProgressBarBuilder()
                                .setTaskName("#01"))
                                .setInitialMax(100)
                                .setConsumer(new ConsoleMultiProgressBarConsumer(new PrintStream(new FileOutputStream(FileDescriptor.out)),
                                                                                 1))
                                .hideEta()
                                .setUpdateIntervalMillis(100)
                                .build();
new ProgressBarBuilder()
                                .setTaskName("#02"))
                                .setInitialMax(100)
                                .setConsumer(new ConsoleMultiProgressBarConsumer(new PrintStream(new FileOutputStream(FileDescriptor.out)),
                                                                                 2))
                                .hideEta()
                                .setUpdateIntervalMillis(100)
                                .build();
new ProgressBarBuilder()
                                .setTaskName("#03"))
                                .setInitialMax(100)
                                .setConsumer(new ConsoleMultiProgressBarConsumer(new PrintStream(new FileOutputStream(FileDescriptor.out)),
                                                                                 3))
                                .hideEta()
                                .setUpdateIntervalMillis(100)
                                .build();

i dont really understand this, where are the matcher and sb in the accept method coming from?

oh!that's my fault,I have omitted some irrelevant code,The correct content is this out.print(str);

Lc3586 avatar Aug 18 '23 06:08 Lc3586