diff --git a/README.md b/README.md index 71f5cfc..86d1cd0 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,7 @@ // simulating some work max := 100 * time.Millisecond for i := 0; i < total; i++ { + bar.StartBlock() time.Sleep(time.Duration(rand.Intn(10)+1) * max / 10) // increment by 1 (there is bar.IncrBy(int) method, if needed) bar.Increment() @@ -90,6 +91,7 @@ defer wg.Done() max := 100 * time.Millisecond for i := 0; i < total; i++ { + bar.StartBlock() time.Sleep(time.Duration(rand.Intn(10)+1) * max / 10) bar.Increment() } diff --git a/bar.go b/bar.go index 6f7f100..95e9828 100644 --- a/bar.go +++ b/bar.go @@ -57,7 +57,6 @@ etaAlpha float64 total int64 current int64 - lastIncrement int64 totalAutoIncrTrigger int64 totalAutoIncrBy int64 trimLeftSpace bool @@ -241,23 +240,29 @@ } } +// StartBlock updates start timestamp of the current increment block. +// It is optional to call, unless ETA decorator is used. +// If *bar.ProxyReader is used, it will be called implicitly. +func (b *Bar) StartBlock() { + now := time.Now() + select { + case b.operateState <- func(s *bState) { s.blockStartTime = now }: + case <-b.done: + } +} + // IncrBy increments progress bar by amount of n func (b *Bar) IncrBy(n int) { - if n < 1 { - return - } now := time.Now() select { case b.operateState <- func(s *bState) { if s.current == 0 { s.startTime = now } else { - s.updateETA(now.Sub(s.blockStartTime)) s.timeElapsed = now.Sub(s.startTime) } - s.blockStartTime = now - s.lastIncrement = int64(n) - s.current += s.lastIncrement + s.current += int64(n) + s.updateETA(n, now.Sub(s.blockStartTime)) if s.dynamic { curp := decor.CalcPercentage(s.total, s.current, 100) if 100-curp <= s.totalAutoIncrTrigger { @@ -293,7 +298,6 @@ s.toComplete = true cancel = nil case <-b.shutdown: - s.updateETA(time.Since(s.blockStartTime)) b.cacheState = s close(b.done) return @@ -429,8 +433,8 @@ } } -func (s *bState) updateETA(lastBlockTime time.Duration) { - lastItemEstimate := float64(lastBlockTime) / float64(s.lastIncrement) +func (s *bState) updateETA(n int, lastBlockTime time.Duration) { + lastItemEstimate := float64(lastBlockTime) / float64(n) s.timePerItemEstimate = time.Duration((s.etaAlpha * lastItemEstimate) + (1-s.etaAlpha)*float64(s.timePerItemEstimate)) s.timeRemaining = time.Duration(s.total-s.current) * s.timePerItemEstimate } diff --git a/decor/decorators.go b/decor/decorators.go index 1238661..29f11ef 100644 --- a/decor/decorators.go +++ b/decor/decorators.go @@ -177,6 +177,9 @@ // `width` width reservation to apply, ignored if `DwidthSync` bit is set // // `conf` bit set config, [DidentRight|DwidthSync|DextraSpace] +// +// To correctly estimate non io progress, *Bar.StartBlock should be called, +// before each increment block. func ETA(width, conf int) DecoratorFunc { format := "%%" if (conf & DidentRight) != 0 { diff --git a/examples/cancel/main.go b/examples/cancel/main.go index 11b7e74..7ea7b8f 100644 --- a/examples/cancel/main.go +++ b/examples/cancel/main.go @@ -46,6 +46,7 @@ defer wg.Done() max := 100 * time.Millisecond for !bar.Completed() { + bar.StartBlock() time.Sleep(time.Duration(rand.Intn(10)+1) * max / 10) bar.Increment() } @@ -53,5 +54,4 @@ } p.Wait() - fmt.Println("done") } diff --git a/examples/complex/main.go b/examples/complex/main.go index 06cedea..d87316c 100644 --- a/examples/complex/main.go +++ b/examples/complex/main.go @@ -69,6 +69,7 @@ defer wg.Done() max := 100 * time.Millisecond for !b.Completed() { + b.StartBlock() time.Sleep(time.Duration(rand.Intn(10)+1) * max / 10) b.IncrBy(incrBy) } diff --git a/examples/io/single/main.go b/examples/io/single/main.go index 83219ed..15cd584 100644 --- a/examples/io/single/main.go +++ b/examples/io/single/main.go @@ -43,6 +43,7 @@ decor.CountersKibiByte("% 6.1f / % 6.1f", 18, 0), ), mpb.AppendDecorators( + decor.ETA(0, 0), decor.SpeedKibiByte("% 6.1f", 18, 0), ), ) diff --git a/examples/prependETA/main.go b/examples/prependETA/main.go index 60b75e5..1f83e5c 100644 --- a/examples/prependETA/main.go +++ b/examples/prependETA/main.go @@ -39,6 +39,7 @@ defer wg.Done() max := 100 * time.Millisecond for i := 0; i < total; i++ { + b.StartBlock() time.Sleep(time.Duration(rand.Intn(10)+1) * max / 10) b.Increment() } diff --git a/examples/prependElapsed/main.go b/examples/prependElapsed/main.go index 3def410..0df1581 100644 --- a/examples/prependElapsed/main.go +++ b/examples/prependElapsed/main.go @@ -47,5 +47,4 @@ } p.Wait() - fmt.Println("done") } diff --git a/examples/remove/main.go b/examples/remove/main.go index 4e5d785..fc2e220 100644 --- a/examples/remove/main.go +++ b/examples/remove/main.go @@ -44,6 +44,7 @@ defer wg.Done() max := 100 * time.Millisecond for i := 0; i < total; i++ { + b.StartBlock() if b.ID() == 2 && i == 42 { p.Abort(b) return @@ -55,5 +56,4 @@ } p.Wait() - fmt.Println("done") } diff --git a/examples/simple/main.go b/examples/simple/main.go index 9748667..63cf10d 100644 --- a/examples/simple/main.go +++ b/examples/simple/main.go @@ -39,6 +39,7 @@ defer wg.Done() max := 100 * time.Millisecond for i := 0; i < total; i++ { + bar.StartBlock() time.Sleep(time.Duration(rand.Intn(10)+1) * max / 10) bar.Increment() } diff --git a/examples/singleBar/main.go b/examples/singleBar/main.go index 4b7ac39..e32266a 100644 --- a/examples/singleBar/main.go +++ b/examples/singleBar/main.go @@ -37,6 +37,7 @@ // simulating some work max := 100 * time.Millisecond for i := 0; i < total; i++ { + bar.StartBlock() time.Sleep(time.Duration(rand.Intn(10)+1) * max / 10) // Increment by 1 (there is bar.IncrBy(int) method, if needed) bar.Increment() diff --git a/examples/sort/main.go b/examples/sort/main.go index 699ac07..2c7dfc5 100644 --- a/examples/sort/main.go +++ b/examples/sort/main.go @@ -39,6 +39,7 @@ defer wg.Done() max := 100 * time.Millisecond for i := 0; i < total; i++ { + b.StartBlock() time.Sleep(time.Duration(rand.Intn(10)+1) * max / 10) if i&1 == 1 { priority := total - int(b.Current()) @@ -50,5 +51,4 @@ } p.Wait() - fmt.Println("done") } diff --git a/examples/stress/main.go b/examples/stress/main.go index 0988f70..dfdd92f 100644 --- a/examples/stress/main.go +++ b/examples/stress/main.go @@ -41,6 +41,7 @@ defer wg.Done() max := 100 * time.Millisecond for i := 0; i < total; i++ { + bar.StartBlock() time.Sleep(time.Duration(rand.Intn(10)+1) * max / 10) bar.Increment() } @@ -48,5 +49,4 @@ } p.Wait() - fmt.Println("done") } diff --git a/proxyreader.go b/proxyreader.go index aa28496..c333ad8 100644 --- a/proxyreader.go +++ b/proxyreader.go @@ -9,6 +9,7 @@ } func (r *Reader) Read(p []byte) (int, error) { + r.bar.StartBlock() n, err := r.Reader.Read(p) r.bar.IncrBy(n) return n, err