erm/vendor/github.com/lxn/walk/stopwatch.go

138 lines
2.5 KiB
Go

// Copyright 2019 The Walk Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build windows
package walk
import (
"bytes"
"fmt"
"sort"
"sync"
"text/tabwriter"
"time"
)
type stopwatchItem struct {
stopwatchStats
subject string
startedTime time.Time
}
type stopwatchStats struct {
count int64
min time.Duration
max time.Duration
total time.Duration
}
func (sws *stopwatchStats) Average() time.Duration {
if sws.count == 0 {
return 0
}
return time.Nanosecond * time.Duration(sws.total.Nanoseconds()/sws.count)
}
type stopwatch struct {
mutex sync.Mutex
subject2item map[string]*stopwatchItem
}
func newStopwatch() *stopwatch {
return &stopwatch{
subject2item: make(map[string]*stopwatchItem),
}
}
func (sw *stopwatch) Start(subject string) time.Time {
sw.mutex.Lock()
defer sw.mutex.Unlock()
item, ok := sw.subject2item[subject]
if !ok {
item = &stopwatchItem{subject: subject}
sw.subject2item[subject] = item
}
item.startedTime = time.Now()
return item.startedTime
}
func (sw *stopwatch) Stop(subject string) time.Duration {
sw.mutex.Lock()
defer sw.mutex.Unlock()
item, ok := sw.subject2item[subject]
if !ok || item.startedTime.IsZero() {
return 0
}
duration := time.Now().Sub(item.startedTime)
item.count++
if duration < item.min || item.min == 0 {
item.min = duration
}
if duration > item.max {
item.max = duration
}
item.total += duration
item.startedTime = time.Time{}
return duration
}
func (sw *stopwatch) Cancel(subject string) {
sw.mutex.Lock()
defer sw.mutex.Unlock()
item, ok := sw.subject2item[subject]
if !ok {
return
}
item.startedTime = time.Time{}
}
func (sw *stopwatch) Clear() {
sw.mutex.Lock()
defer sw.mutex.Unlock()
for key := range sw.subject2item {
delete(sw.subject2item, key)
}
}
func (sw *stopwatch) Print() {
sw.mutex.Lock()
items := make([]*stopwatchItem, 0, len(sw.subject2item))
for _, item := range sw.subject2item {
items = append(items, item)
}
sw.mutex.Unlock()
sort.Slice(items, func(i, j int) bool {
return items[i].total > items[j].total
})
var buf bytes.Buffer
writer := tabwriter.NewWriter(&buf, 0, 8, 2, ' ', tabwriter.AlignRight)
fmt.Fprintln(writer, "#\tSubject\tAverage\tTotal\tMin\tMax\t\tCount")
for i, item := range items {
fmt.Fprintf(writer, "%d\t%s\t%s\t%s\t%s\t%s\t\t%d\n", i+1, item.subject, item.Average(), item.total, item.min, item.max, item.count)
}
writer.Flush()
fmt.Print(buf.String())
}