Update dependencies
This commit is contained in:
145
vendor/gvisor.dev/gvisor/pkg/state/stats.go
vendored
Normal file
145
vendor/gvisor.dev/gvisor/pkg/state/stats.go
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
// Copyright 2018 The gVisor Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package state
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"sort"
|
||||
"time"
|
||||
)
|
||||
|
||||
type statEntry struct {
|
||||
count uint
|
||||
total time.Duration
|
||||
}
|
||||
|
||||
// Stats tracks encode / decode timing.
|
||||
//
|
||||
// This currently provides a meaningful String function and no other way to
|
||||
// extract stats about individual types.
|
||||
//
|
||||
// All exported receivers accept nil.
|
||||
type Stats struct {
|
||||
// byType contains a breakdown of time spent by type.
|
||||
//
|
||||
// This is indexed *directly* by typeID, including zero.
|
||||
byType []statEntry
|
||||
|
||||
// stack contains objects in progress.
|
||||
stack []typeID
|
||||
|
||||
// names contains type names.
|
||||
//
|
||||
// This is also indexed *directly* by typeID, including zero, which we
|
||||
// hard-code as "state.default". This is only resolved by calling fini
|
||||
// on the stats object.
|
||||
names []string
|
||||
|
||||
// last is the last start time.
|
||||
last time.Time
|
||||
}
|
||||
|
||||
// init initializes statistics.
|
||||
func (s *Stats) init() {
|
||||
s.last = time.Now()
|
||||
s.stack = append(s.stack, 0)
|
||||
}
|
||||
|
||||
// fini finalizes statistics.
|
||||
func (s *Stats) fini(resolve func(id typeID) string) {
|
||||
s.done()
|
||||
|
||||
// Resolve all type names.
|
||||
s.names = make([]string, len(s.byType))
|
||||
s.names[0] = "state.default" // See above.
|
||||
for id := typeID(1); int(id) < len(s.names); id++ {
|
||||
s.names[id] = resolve(id)
|
||||
}
|
||||
}
|
||||
|
||||
// sample adds the samples to the given object.
|
||||
func (s *Stats) sample(id typeID) {
|
||||
now := time.Now()
|
||||
if len(s.byType) <= int(id) {
|
||||
// Allocate all the missing entries in one fell swoop.
|
||||
s.byType = append(s.byType, make([]statEntry, 1+int(id)-len(s.byType))...)
|
||||
}
|
||||
s.byType[id].total += now.Sub(s.last)
|
||||
s.last = now
|
||||
}
|
||||
|
||||
// start starts a sample.
|
||||
func (s *Stats) start(id typeID) {
|
||||
last := s.stack[len(s.stack)-1]
|
||||
s.sample(last)
|
||||
s.stack = append(s.stack, id)
|
||||
}
|
||||
|
||||
// done finishes the current sample.
|
||||
func (s *Stats) done() {
|
||||
last := s.stack[len(s.stack)-1]
|
||||
s.sample(last)
|
||||
s.byType[last].count++
|
||||
s.stack = s.stack[:len(s.stack)-1]
|
||||
}
|
||||
|
||||
type sliceEntry struct {
|
||||
name string
|
||||
entry *statEntry
|
||||
}
|
||||
|
||||
// String returns a table representation of the stats.
|
||||
func (s *Stats) String() string {
|
||||
// Build a list of stat entries.
|
||||
ss := make([]sliceEntry, 0, len(s.byType))
|
||||
for id := 0; id < len(s.names); id++ {
|
||||
ss = append(ss, sliceEntry{
|
||||
name: s.names[id],
|
||||
entry: &s.byType[id],
|
||||
})
|
||||
}
|
||||
|
||||
// Sort by total time (descending).
|
||||
sort.Slice(ss, func(i, j int) bool {
|
||||
return ss[i].entry.total > ss[j].entry.total
|
||||
})
|
||||
|
||||
// Print the stat results.
|
||||
var (
|
||||
buf bytes.Buffer
|
||||
count uint
|
||||
total time.Duration
|
||||
)
|
||||
buf.WriteString("\n")
|
||||
buf.WriteString(fmt.Sprintf("% 16s | % 8s | % 16s | %s\n", "total", "count", "per", "type"))
|
||||
buf.WriteString("-----------------+----------+------------------+----------------\n")
|
||||
for _, se := range ss {
|
||||
if se.entry.count == 0 {
|
||||
// Since we store all types linearly, we are not
|
||||
// guaranteed that any entry actually has time.
|
||||
continue
|
||||
}
|
||||
count += se.entry.count
|
||||
total += se.entry.total
|
||||
per := se.entry.total / time.Duration(se.entry.count)
|
||||
buf.WriteString(fmt.Sprintf("% 16s | %8d | % 16s | %s\n",
|
||||
se.entry.total, se.entry.count, per, se.name))
|
||||
}
|
||||
buf.WriteString("-----------------+----------+------------------+----------------\n")
|
||||
buf.WriteString(fmt.Sprintf("% 16s | % 8d | % 16s | [all]",
|
||||
total, count, total/time.Duration(count)))
|
||||
return string(buf.Bytes())
|
||||
}
|
||||
Reference in New Issue
Block a user