Code Monkey home page Code Monkey logo

zzz's Introduction

๐Ÿ’ค

Crates.io docs.rs MIT licensed Apache 2.0 licensed

The progress bar with sane defaults that doesn't slow down your loops. Inspired by tqdm.

Screenshot

[dependencies]
zzz = "0.3"

Features

  • Seamless integration with iterators and streams
    • If possible, zzz infers the target size from size_hint()
  • Automagically determines and updates a good printing frequency
  • Very low overhead: doesn't slow down your loop, pretty much no matter how simple the loop body. On Skylake, the average overhead per iteration for a
    • !Sync/add based progress bar is 3 CPU cycles
    • Sync/add_sync based progress bar is ~40 CPU cycles (depends on how many threads are updating the shared state)

Cargo Features

  • streams: Enables support for .progress() on async streams (futures::streams::Stream)

Usage examples

Adding a progress bar to an iterator

use zzz::ProgressBarIterExt as _;

for _ in (0..1000).into_iter().progress() {
    //                         ^^^^^^^^
}

If size_hint() for the iterator defines an upper bound, it is automatically taken as the target. Otherwise, a progress indicator ("spinner") is displayed.

Manually creating and advancing a progress bar

use zzz::ProgressBar;

let mut pb = ProgressBar::with_target(1234);
for _ in 0..1234 {
    pb.add(1);
}

Manually creating a spinner (for unknown target progress indicator)

use zzz::ProgressBar;

let mut pb = ProgressBar::spinner();
for _ in 0..5678 {
    pb.add(1);
}

zzz's People

Contributors

athre0z avatar frereit avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Forkers

azriel91 frereit

zzz's Issues

Sane behaviour when not attached to a tty

When the application printing the progress bar is not attached to a terminal, we definitely shouldn't be flooding stdout at 60 refreshes per second. When the application is printing to e.g. a docker log, we'd cause an unreasonable amount of disk space usage. A separate formatter / printer should be used when a non-tty is detected, printing significantly less frequently.

feature: Conditional progress bar based on log level

I have the following use case:

I want to display the progress bar only if the log level is set to "INFO" or higher (as specified by the log crate).

Currently, I implement the following trait manually inside my crate:

use log::{log_enabled, Level};
use zzz::{ProgressBarIterExt, ProgressBarIter};


// Helper type to hold the iterator, with a progress bar if desired
pub(crate) enum OptionalProgressBarIter<I: Iterator> {
    Enabled(ProgressBarIter<I>),
    Disabled(I),
}

impl<I: Iterator> Iterator for OptionalProgressBarIter<I> {
    type Item = I::Item;

    fn next(&mut self) -> Option<Self::Item> {
        // Simply iterate from the underlying iterator
        match self {
            OptionalProgressBarIter::Enabled(iter) => iter.next(),
            OptionalProgressBarIter::Disabled(iter) => iter.next(),
        }
    }
}

pub(crate) trait ProgressBarIterLogExt: Iterator {
    fn progress_with_level<'a>(self, level: Level) -> OptionalProgressBarIter<Self>
    where
        Self: Sized + 'a,
    {
        if log_enabled!(level) {
            OptionalProgressBarIter::Enabled(self.progress())
        } else {
            OptionalProgressBarIter::Disabled(self)
        }
    }
}
impl<I> ProgressBarIterLogExt for I where I: Iterator {}

This API can then be used like this:

some_iterator.progress_with_level(Level::Info)

Is this API something that you would consider adding into your crate? I think this is a common enough use case to warrant it but it's up to you.

Bug: `ProgressBar` not redrawing when using `ParallelIterator` from `rayon`

I am trying to create a ProgressBar over an iterator created using the rayon crate:

use std::thread;
use std::time::Duration;

use rayon::prelude::*;
use zzz::ProgressBar;

fn main() {
    let elems = vec![0; 10000];
    let pb = ProgressBar::with_target(elems.len());
    elems.par_iter().for_each(|_| {
        pb.add_sync(1);
        thread::sleep(Duration::from_millis(5));
    });
}
[dependencies]
rayon = "1.7.0"
zzz = "0.2.1"

However, this does not seem to work as expected. The progress bar appears:

  0.04% |โ–                                                                                                 | 4.00/10.00K [00:00:01] (8.91K it/s

but is then not redrawn until the iterator completes:

100.00% |โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–| 10.00K/10.00K [00:00:00] (1.17K it/s)

When replacing the .par_iter() with a normal .iter(), this works as expected and the progress bar is smoothly redrawn. Is this an issue with the implementation of add_sync inside zzz?

This might be user error, so apologies in advance if that is the case.

Edit: whoops, I accidentally submitted the issue too early. sorry about that.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.