Fix #20
Vladimir Bauer
8 years ago
| 55 | 55 | // simulating some work |
| 56 | 56 | max := 100 * time.Millisecond |
| 57 | 57 | for i := 0; i < total; i++ { |
| 58 | bar.StartBlock() | |
| 58 | 59 | time.Sleep(time.Duration(rand.Intn(10)+1) * max / 10) |
| 59 | 60 | // increment by 1 (there is bar.IncrBy(int) method, if needed) |
| 60 | 61 | bar.Increment() |
| 89 | 90 | defer wg.Done() |
| 90 | 91 | max := 100 * time.Millisecond |
| 91 | 92 | for i := 0; i < total; i++ { |
| 93 | bar.StartBlock() | |
| 92 | 94 | time.Sleep(time.Duration(rand.Intn(10)+1) * max / 10) |
| 93 | 95 | bar.Increment() |
| 94 | 96 | } |
| 56 | 56 | etaAlpha float64 |
| 57 | 57 | total int64 |
| 58 | 58 | current int64 |
| 59 | lastIncrement int64 | |
| 60 | 59 | totalAutoIncrTrigger int64 |
| 61 | 60 | totalAutoIncrBy int64 |
| 62 | 61 | trimLeftSpace bool |
| 240 | 239 | } |
| 241 | 240 | } |
| 242 | 241 | |
| 242 | // StartBlock updates start timestamp of the current increment block. | |
| 243 | // It is optional to call, unless ETA decorator is used. | |
| 244 | // If *bar.ProxyReader is used, it will be called implicitly. | |
| 245 | func (b *Bar) StartBlock() { | |
| 246 | now := time.Now() | |
| 247 | select { | |
| 248 | case b.operateState <- func(s *bState) { s.blockStartTime = now }: | |
| 249 | case <-b.done: | |
| 250 | } | |
| 251 | } | |
| 252 | ||
| 243 | 253 | // IncrBy increments progress bar by amount of n |
| 244 | 254 | func (b *Bar) IncrBy(n int) { |
| 245 | if n < 1 { | |
| 246 | return | |
| 247 | } | |
| 248 | 255 | now := time.Now() |
| 249 | 256 | select { |
| 250 | 257 | case b.operateState <- func(s *bState) { |
| 251 | 258 | if s.current == 0 { |
| 252 | 259 | s.startTime = now |
| 253 | 260 | } else { |
| 254 | s.updateETA(now.Sub(s.blockStartTime)) | |
| 255 | 261 | s.timeElapsed = now.Sub(s.startTime) |
| 256 | 262 | } |
| 257 | s.blockStartTime = now | |
| 258 | s.lastIncrement = int64(n) | |
| 259 | s.current += s.lastIncrement | |
| 263 | s.current += int64(n) | |
| 264 | s.updateETA(n, now.Sub(s.blockStartTime)) | |
| 260 | 265 | if s.dynamic { |
| 261 | 266 | curp := decor.CalcPercentage(s.total, s.current, 100) |
| 262 | 267 | if 100-curp <= s.totalAutoIncrTrigger { |
| 292 | 297 | s.toComplete = true |
| 293 | 298 | cancel = nil |
| 294 | 299 | case <-b.shutdown: |
| 295 | s.updateETA(time.Since(s.blockStartTime)) | |
| 296 | 300 | b.cacheState = s |
| 297 | 301 | close(b.done) |
| 298 | 302 | return |
| 428 | 432 | } |
| 429 | 433 | } |
| 430 | 434 | |
| 431 | func (s *bState) updateETA(lastBlockTime time.Duration) { | |
| 432 | lastItemEstimate := float64(lastBlockTime) / float64(s.lastIncrement) | |
| 435 | func (s *bState) updateETA(n int, lastBlockTime time.Duration) { | |
| 436 | lastItemEstimate := float64(lastBlockTime) / float64(n) | |
| 433 | 437 | s.timePerItemEstimate = time.Duration((s.etaAlpha * lastItemEstimate) + (1-s.etaAlpha)*float64(s.timePerItemEstimate)) |
| 434 | 438 | s.timeRemaining = time.Duration(s.total-s.current) * s.timePerItemEstimate |
| 435 | 439 | } |
| 176 | 176 | // `width` width reservation to apply, ignored if `DwidthSync` bit is set |
| 177 | 177 | // |
| 178 | 178 | // `conf` bit set config, [DidentRight|DwidthSync|DextraSpace] |
| 179 | // | |
| 180 | // To correctly estimate non io progress, *Bar.StartBlock should be called, | |
| 181 | // before each increment block. | |
| 179 | 182 | func ETA(width, conf int) DecoratorFunc { |
| 180 | 183 | format := "%%" |
| 181 | 184 | if (conf & DidentRight) != 0 { |
| 45 | 45 | defer wg.Done() |
| 46 | 46 | max := 100 * time.Millisecond |
| 47 | 47 | for !bar.Completed() { |
| 48 | bar.StartBlock() | |
| 48 | 49 | time.Sleep(time.Duration(rand.Intn(10)+1) * max / 10) |
| 49 | 50 | bar.Increment() |
| 50 | 51 | } |
| 52 | 53 | } |
| 53 | 54 | |
| 54 | 55 | p.Wait() |
| 55 | fmt.Println("done") | |
| 56 | 56 | } |
| 68 | 68 | defer wg.Done() |
| 69 | 69 | max := 100 * time.Millisecond |
| 70 | 70 | for !b.Completed() { |
| 71 | b.StartBlock() | |
| 71 | 72 | time.Sleep(time.Duration(rand.Intn(10)+1) * max / 10) |
| 72 | 73 | b.IncrBy(incrBy) |
| 73 | 74 | } |
| 42 | 42 | decor.CountersKibiByte("% 6.1f / % 6.1f", 18, 0), |
| 43 | 43 | ), |
| 44 | 44 | mpb.AppendDecorators( |
| 45 | decor.ETA(0, 0), | |
| 45 | 46 | decor.SpeedKibiByte("% 6.1f", 18, 0), |
| 46 | 47 | ), |
| 47 | 48 | ) |
| 38 | 38 | defer wg.Done() |
| 39 | 39 | max := 100 * time.Millisecond |
| 40 | 40 | for i := 0; i < total; i++ { |
| 41 | b.StartBlock() | |
| 41 | 42 | time.Sleep(time.Duration(rand.Intn(10)+1) * max / 10) |
| 42 | 43 | b.Increment() |
| 43 | 44 | } |
| 43 | 43 | defer wg.Done() |
| 44 | 44 | max := 100 * time.Millisecond |
| 45 | 45 | for i := 0; i < total; i++ { |
| 46 | b.StartBlock() | |
| 46 | 47 | if b.ID() == 2 && i == 42 { |
| 47 | 48 | p.Abort(b) |
| 48 | 49 | return |
| 54 | 55 | } |
| 55 | 56 | |
| 56 | 57 | p.Wait() |
| 57 | fmt.Println("done") | |
| 58 | 58 | } |
| 38 | 38 | defer wg.Done() |
| 39 | 39 | max := 100 * time.Millisecond |
| 40 | 40 | for i := 0; i < total; i++ { |
| 41 | bar.StartBlock() | |
| 41 | 42 | time.Sleep(time.Duration(rand.Intn(10)+1) * max / 10) |
| 42 | 43 | bar.Increment() |
| 43 | 44 | } |
| 36 | 36 | // simulating some work |
| 37 | 37 | max := 100 * time.Millisecond |
| 38 | 38 | for i := 0; i < total; i++ { |
| 39 | bar.StartBlock() | |
| 39 | 40 | time.Sleep(time.Duration(rand.Intn(10)+1) * max / 10) |
| 40 | 41 | // Increment by 1 (there is bar.IncrBy(int) method, if needed) |
| 41 | 42 | bar.Increment() |
| 38 | 38 | defer wg.Done() |
| 39 | 39 | max := 100 * time.Millisecond |
| 40 | 40 | for i := 0; i < total; i++ { |
| 41 | b.StartBlock() | |
| 41 | 42 | time.Sleep(time.Duration(rand.Intn(10)+1) * max / 10) |
| 42 | 43 | if i&1 == 1 { |
| 43 | 44 | priority := total - int(b.Current()) |
| 49 | 50 | } |
| 50 | 51 | |
| 51 | 52 | p.Wait() |
| 52 | fmt.Println("done") | |
| 53 | 53 | } |