github.com/jgbaldwinbrown/perf@v0.1.1/benchproc/keyheader.go (about) 1 // Copyright 2022 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package benchproc 6 7 // A KeyHeader represents a slice of Keys, combined into a forest of 8 // trees by common Field values. This is intended to visually present a 9 // sequence of Keys in a compact form; primarily, as a header on a 10 // table. 11 // 12 // All Keys must have the same Projection. The levels of the tree 13 // correspond to the Fields of the Projection, and the depth of the tree 14 // is exactly the number of Fields. A node at level i represents a 15 // subslice of the Keys that all have the same values as each other for 16 // fields 0 through i. 17 // 18 // For example, given four keys: 19 // 20 // K[0] = a:1 b:1 c:1 21 // K[1] = a:1 b:1 c:2 22 // K[2] = a:2 b:2 c:2 23 // K[3] = a:2 b:3 c:3 24 // 25 // the KeyHeader is as follows: 26 // 27 // Level 0 a:1 a:2 28 // | / \ 29 // Level 1 b:1 b:2 b:3 30 // / \ | | 31 // Level 2 c:1 c:2 c:2 c:3 32 // K[0] K[1] K[2] K[3] 33 type KeyHeader struct { 34 // Keys is the sequence of keys at the leaf level of this tree. 35 // Each level subdivides this sequence. 36 Keys []Key 37 38 // Levels are the labels for each level of the tree. Level i of the 39 // tree corresponds to the i'th field of all Keys. 40 Levels []*Field 41 42 // Top is the list of tree roots. These nodes are all at level 0. 43 Top []*KeyHeaderNode 44 } 45 46 // KeyHeaderNode is a node in a KeyHeader. 47 type KeyHeaderNode struct { 48 // Field is the index into KeyHeader.Levels of the Field represented 49 // by this node. This is also the level of this node in the tree, 50 // starting with 0 at the top. 51 Field int 52 53 // Value is the value that all Keys have in common for Field. 54 Value string 55 56 // Start is the index of the first Key covered by this node. 57 Start int 58 // Len is the number of Keys in the sequence represented by this node. 59 // This is also the number of leaf nodes in the subtree at this node. 60 Len int 61 62 // Children are the children of this node. These are all at level Field+1. 63 // Child i+1 differs from child i in the value of field Field+1. 64 Children []*KeyHeaderNode 65 } 66 67 // NewKeyHeader computes the KeyHeader of a slice of Keys by combining 68 // common prefixes of fields. 69 func NewKeyHeader(keys []Key) *KeyHeader { 70 if len(keys) == 0 { 71 return &KeyHeader{} 72 } 73 74 fields := commonProjection(keys).FlattenedFields() 75 76 var walk func(parent *KeyHeaderNode) 77 walk = func(parent *KeyHeaderNode) { 78 level := parent.Field + 1 79 if level == len(fields) { 80 return 81 } 82 field := fields[level] 83 var node *KeyHeaderNode 84 for j, key := range keys[parent.Start : parent.Start+parent.Len] { 85 val := key.Get(field) 86 if node != nil && val == node.Value { 87 // Add this key to the current node. 88 node.Len++ 89 } else { 90 // Start a new node. 91 node = &KeyHeaderNode{level, val, parent.Start + j, 1, nil} 92 parent.Children = append(parent.Children, node) 93 } 94 } 95 for _, child := range parent.Children { 96 walk(child) 97 } 98 } 99 root := &KeyHeaderNode{-1, "", 0, len(keys), nil} 100 walk(root) 101 return &KeyHeader{keys, fields, root.Children} 102 }