Codebase list golang-github-vbauerster-mpb / 1011a0f
elapsed calculations Vladimir Bauer 9 years ago
2 changed file(s) with 97 addition(s) and 25 deletion(s). Raw diff Collapse all Expand all
4141 flushedCh chan struct{}
4242 stopCh chan struct{}
4343 done chan struct{}
44
45 timePerItemEstimate time.Duration
4644 }
4745
4846 type Statistics struct {
49 Total, Completed int
50 TimePerItemEstimate time.Duration
47 Total, Current int
48 TimeElapsed, TimePerItemEstimate time.Duration
5149 }
5250
5351 func (s *Statistics) eta() time.Duration {
54 return time.Duration(s.Total-s.Completed) * s.TimePerItemEstimate
52 return time.Duration(s.Total-s.Current) * s.TimePerItemEstimate
5553 }
5654
5755 func newBar(total, width int, wg *sync.WaitGroup) *Bar {
190188 return b
191189 }
192190
191 func (b *Bar) PrependElapsed(padding int) *Bar {
192 layout := "%" + strconv.Itoa(padding) + "s"
193 b.PrependFunc(func(s *Statistics) string {
194 return fmt.Sprintf(layout, time.Duration(s.TimeElapsed.Seconds())*time.Second)
195 })
196 return b
197 }
198
199 func (b *Bar) AppendElapsed() *Bar {
200 b.AppendFunc(func(s *Statistics) string {
201 return fmt.Sprint(time.Duration(s.TimeElapsed.Seconds()) * time.Second)
202 })
203 return b
204 }
205
193206 func (b *Bar) AppendPercentage() *Bar {
194207 b.AppendFunc(func(s *Statistics) string {
195 completed := int(100 * float64(s.Completed) / float64(s.Total))
208 completed := int(100 * float64(s.Current) / float64(s.Total))
196209 return fmt.Sprintf("%3d %%", completed)
197210 })
198211 return b
201214 func (b *Bar) PrependPercentage(padding int) *Bar {
202215 layout := "%" + strconv.Itoa(padding) + "d %%"
203216 b.PrependFunc(func(s *Statistics) string {
204 completed := int(100 * float64(s.Completed) / float64(s.Total))
217 completed := int(100 * float64(s.Current) / float64(s.Total))
205218 return fmt.Sprintf(layout, completed)
206219 })
207220 return b
208221 }
209222
210223 func (b *Bar) server(wg *sync.WaitGroup) {
211 var completed int
212 blockStartTime := time.Now()
224 timeStarted := time.Now()
225 blockStartTime := timeStarted
213226 buf := make([]byte, b.width, b.width+24)
227 var tpie time.Duration
228 var timeElapsed time.Duration
214229 var appendFuncs []DecoratorFunc
215230 var prependFuncs []DecoratorFunc
216231 var done bool
232 var current int
217233 for {
218234 select {
219235 case i := <-b.incrCh:
220 n := completed + i
236 n := current + i
221237 // fmt.Fprintf(os.Stderr, "n = %+v\n", n)
222238 if n > b.total {
223 completed = b.total
239 current = b.total
224240 done = true
225241 break
226242 }
227 b.updateTimePerItemEstimate(i, blockStartTime)
228 completed = n
229 if completed == b.total && !done {
243 timeElapsed = time.Since(timeStarted)
244 tpie = calcTimePerItemEstimate(tpie, blockStartTime, b.alpha, i)
245 blockStartTime = time.Now()
246 current = n
247 if current == b.total && !done {
230248 done = true
231249 }
232 blockStartTime = time.Now()
233250 case d := <-b.decoratorCh:
234251 switch d.kind {
235252 case decoratorAppend:
238255 prependFuncs = append(prependFuncs, d.f)
239256 }
240257 case respCh := <-b.redrawReqCh:
241 respCh <- b.draw(buf, completed, appendFuncs, prependFuncs)
258 stat := &Statistics{b.total, current, timeElapsed, tpie}
259 respCh <- b.draw(stat, buf, appendFuncs, prependFuncs)
242260 case respCh := <-b.progressReqCh:
243 respCh <- int(100 * float64(completed) / float64(b.total))
261 respCh <- int(100 * float64(current) / float64(b.total))
244262 case <-b.flushedCh:
245263 if done && !b.IsCompleted() {
246264 // fmt.Fprintln(os.Stderr, "flushedCh: wg.Done")
259277 }
260278 }
261279
262 func (b *Bar) draw(buf []byte, current int, appendFuncs, prependFuncs []DecoratorFunc) []byte {
263 completedWidth := current * b.width / b.total
280 func (b *Bar) draw(stat *Statistics, buf []byte, appendFuncs, prependFuncs []DecoratorFunc) []byte {
281 completedWidth := stat.Current * b.width / b.total
264282
265283 for i := 0; i < completedWidth; i++ {
266284 buf[i] = b.fill
276294 // set left and right ends bits
277295 buf[0], buf[len(buf)-1] = b.leftEnd, b.rightEnd
278296
279 s := &Statistics{b.total, current, b.timePerItemEstimate}
280
281297 // render append functions to the right of the bar
282298 for _, f := range appendFuncs {
283299 buf = append(buf, ' ')
284 buf = append(buf, []byte(f(s))...)
300 buf = append(buf, []byte(f(stat))...)
285301 }
286302
287303 // render prepend functions to the left of the bar
288304 for _, f := range prependFuncs {
289 args := []byte(f(s))
305 args := []byte(f(stat))
290306 args = append(args, ' ')
291307 buf = append(args, buf...)
292308 }
293309 return buf
294310 }
295311
296 func (b *Bar) updateTimePerItemEstimate(items int, blockStartTime time.Time) {
312 func calcTimePerItemEstimate(tpie time.Duration, blockStartTime time.Time, alpha float64, items int) time.Duration {
297313 lastBlockTime := time.Since(blockStartTime)
298314 lastItemEstimate := float64(lastBlockTime) / float64(items)
299 b.timePerItemEstimate = time.Duration((b.alpha * lastItemEstimate) + (1-b.alpha)*float64(b.timePerItemEstimate))
315 return time.Duration((alpha * lastItemEstimate) + (1-alpha)*float64(tpie))
300316 }
301317
302318 func (b *Bar) progress() int {
0 package main
1
2 import (
3 "fmt"
4 "math/rand"
5 "time"
6
7 "github.com/vbauerster/mpb"
8 )
9
10 const (
11 maxBlockSize = 12
12 )
13
14 func main() {
15
16 p := mpb.New().SetWidth(64)
17
18 name1 := "Bar#1:"
19 bar1 := p.AddBar(50).AppendPercentage().PrependElapsed(3).PrependName(name1, len(name1))
20 go func() {
21 blockSize := rand.Intn(maxBlockSize) + 1
22 for i := 0; i < 50; i++ {
23 time.Sleep(time.Duration(blockSize) * (50*time.Millisecond + time.Duration(rand.Intn(5*int(time.Millisecond)))))
24 bar1.Incr(1)
25 blockSize = rand.Intn(maxBlockSize) + 1
26 }
27 }()
28
29 bar2 := p.AddBar(100).AppendPercentage().PrependElapsed(3).PrependName("", 0-len(name1))
30 go func() {
31 blockSize := rand.Intn(maxBlockSize) + 1
32 for i := 0; i < 100; i++ {
33 time.Sleep(time.Duration(blockSize) * (50*time.Millisecond + time.Duration(rand.Intn(5*int(time.Millisecond)))))
34 bar2.Incr(1)
35 blockSize = rand.Intn(maxBlockSize) + 1
36 }
37 }()
38
39 bar3 := p.AddBar(80).AppendPercentage().PrependElapsed(3).PrependName("Bar#3:", 0)
40 go func() {
41 blockSize := rand.Intn(maxBlockSize) + 1
42 for i := 0; i < 80; i++ {
43 time.Sleep(time.Duration(blockSize) * (50*time.Millisecond + time.Duration(rand.Intn(5*int(time.Millisecond)))))
44 bar3.Incr(1)
45 blockSize = rand.Intn(maxBlockSize) + 1
46 }
47 }()
48
49 // time.Sleep(time.Second)
50 // p.RemoveBar(bar2)
51
52 p.WaitAndStop()
53 fmt.Println("stop")
54 // p.AddBar(1) // panic: send on closed channnel
55 }