github.com/grafana/pyroscope@v1.18.0/pkg/og/storage/tree/tree.go (about) 1 package tree 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "math/big" 7 "sort" 8 "sync" 9 "unsafe" 10 11 "github.com/grafana/pyroscope/pkg/og/structs/merge" 12 ) 13 14 type jsonableSlice []byte 15 16 type treeNode struct { 17 Name jsonableSlice `json:"name,string"` 18 Total uint64 `json:"total"` 19 Self uint64 `json:"self"` 20 ChildrenNodes []*treeNode `json:"children"` 21 } 22 23 func (a jsonableSlice) MarshalJSON() ([]byte, error) { 24 return json.Marshal(string(a)) 25 } 26 27 func (n *treeNode) clone(m, d uint64) *treeNode { 28 newNode := &treeNode{ 29 Name: n.Name, 30 Total: n.Total * m / d, 31 Self: n.Self * m / d, 32 } 33 newNode.ChildrenNodes = make([]*treeNode, len(n.ChildrenNodes)) 34 for i, cn := range n.ChildrenNodes { 35 newNode.ChildrenNodes[i] = cn.clone(m, d) 36 } 37 return newNode 38 } 39 40 func newNode(label []byte) *treeNode { 41 return &treeNode{ 42 Name: label, 43 ChildrenNodes: []*treeNode{}, 44 } 45 } 46 47 const semicolon = byte(';') 48 49 type Tree struct { 50 sync.RWMutex 51 root *treeNode 52 } 53 54 func New() *Tree { 55 return &Tree{ 56 root: newNode([]byte{}), 57 } 58 } 59 60 func (t *Tree) Merge(srcTrieI merge.Merger) { 61 srcTrie := srcTrieI.(*Tree) 62 63 srcNodes := make([]*treeNode, 0, 128) 64 srcNodes = append(srcNodes, srcTrie.root) 65 66 dstNodes := make([]*treeNode, 0, 128) 67 dstNodes = append(dstNodes, t.root) 68 69 for len(srcNodes) > 0 { 70 st := srcNodes[0] 71 srcNodes = srcNodes[1:] 72 73 dt := dstNodes[0] 74 dstNodes = dstNodes[1:] 75 76 dt.Self += st.Self 77 dt.Total += st.Total 78 79 for _, srcChildNode := range st.ChildrenNodes { 80 dstChildNode := dt.insert(srcChildNode.Name) 81 srcNodes = prependTreeNode(srcNodes, srcChildNode) 82 dstNodes = prependTreeNode(dstNodes, dstChildNode) 83 } 84 } 85 } 86 87 func (t *Tree) Diff(x *Tree) *Tree { 88 srcNodes := make([]*treeNode, 1, 128) 89 srcNodes[0] = x.root 90 91 dstNodes := make([]*treeNode, 1, 128) 92 dstNodes[0] = t.root 93 94 for len(srcNodes) > 0 { 95 sn := srcNodes[0] 96 srcNodes = srcNodes[1:] 97 98 dn := dstNodes[0] 99 dstNodes = dstNodes[1:] 100 101 if sn.Total < dn.Total || sn.Self < dn.Self { 102 // src note can not be less than dst node: x always > t. 103 dn.Total = 0 104 dn.Self = 0 105 dn.ChildrenNodes = nil 106 continue 107 } 108 109 dn.Total = sn.Total - dn.Total 110 dn.Self = sn.Self - dn.Self 111 112 var d int 113 for _, sc := range sn.ChildrenNodes { 114 dc := dn.insert(sc.Name) 115 if sc.Total == dc.Total && sc.Self == dc.Self { 116 dn.removeAt(d) 117 continue 118 } 119 dstNodes = prependTreeNode(dstNodes, dc) 120 srcNodes = prependTreeNode(srcNodes, sc) 121 d++ 122 } 123 // Reclaim removed nodes space. 124 for i := d; i < len(dn.ChildrenNodes); i++ { 125 dn.ChildrenNodes[i] = nil 126 } 127 dn.ChildrenNodes = dn.ChildrenNodes[:d] 128 } 129 130 return t 131 } 132 133 func prependTreeNode(s []*treeNode, x *treeNode) []*treeNode { 134 s = append(s, nil) 135 copy(s[1:], s) 136 s[0] = x 137 return s 138 } 139 140 func prependBytes(s [][]byte, x []byte) [][]byte { 141 s = append(s, nil) 142 copy(s[1:], s) 143 s[0] = x 144 return s 145 } 146 147 func prependInt(s []int, x int) []int { 148 s = append(s, 0) 149 copy(s[1:], s) 150 s[0] = x 151 return s 152 } 153 154 func (t *Tree) String() string { 155 return t.Collapsed() 156 } 157 158 func (n *treeNode) insert(targetLabel []byte) *treeNode { 159 i := sort.Search(len(n.ChildrenNodes), func(i int) bool { 160 return bytes.Compare(n.ChildrenNodes[i].Name, targetLabel) >= 0 161 }) 162 if i > len(n.ChildrenNodes)-1 || !bytes.Equal(n.ChildrenNodes[i].Name, targetLabel) { 163 l := make([]byte, len(targetLabel)) 164 copy(l, targetLabel) 165 child := newNode(l) 166 n.ChildrenNodes = append(n.ChildrenNodes, child) 167 copy(n.ChildrenNodes[i+1:], n.ChildrenNodes[i:]) 168 n.ChildrenNodes[i] = child 169 } 170 return n.ChildrenNodes[i] 171 } 172 173 func (n *treeNode) removeAt(i int) { 174 n.ChildrenNodes[i] = nil 175 n.ChildrenNodes = append(n.ChildrenNodes[:i], n.ChildrenNodes[i+1:]...) 176 } 177 178 func (n *treeNode) insertString(targetLabel string) *treeNode { 179 i, j := 0, len(n.ChildrenNodes) 180 for i < j { 181 m := (i + j) >> 1 182 for k, b := range []byte(targetLabel) { 183 if k >= len(n.ChildrenNodes[m].Name) || b > n.ChildrenNodes[m].Name[k] { 184 // targetLabel > n.ChildrenNodes[m].Name 185 i = m + 1 186 break 187 } 188 if b < n.ChildrenNodes[m].Name[k] { 189 // targetLabel < n.ChildrenNodes[m].Name 190 j = m 191 break 192 } 193 if k == len(targetLabel)-1 { 194 if len(targetLabel) == len(n.ChildrenNodes[m].Name) { 195 // targetLabel == n.ChildrenNodes[m].Name 196 return n.ChildrenNodes[m] 197 } 198 // targetLabel < n.ChildrenNodes[m].Name 199 j = m 200 } 201 } 202 } 203 l := []byte(targetLabel) 204 child := newNode(l) 205 n.ChildrenNodes = append(n.ChildrenNodes, child) 206 copy(n.ChildrenNodes[i+1:], n.ChildrenNodes[i:]) 207 n.ChildrenNodes[i] = child 208 return n.ChildrenNodes[i] 209 } 210 211 func (t *Tree) InsertInt(key []byte, value int) { t.Insert(key, uint64(value)) } 212 213 func (t *Tree) Insert(key []byte, value uint64) { 214 node := t.root 215 var offset int 216 for i, k := range key { 217 if k == semicolon { 218 node.Total += value 219 node = node.insert(key[offset:i]) 220 offset = i + 1 221 } 222 } 223 if offset < len(key) { 224 node.Total += value 225 node = node.insert(key[offset:]) 226 } 227 node.Total += value 228 node.Self += value 229 } 230 231 func (t *Tree) InsertStack(stack [][]byte, v uint64) { 232 n := t.root 233 for j := range stack { 234 n.Total += v 235 n = n.insert(stack[j]) 236 } 237 // Leaf. 238 n.Total += v 239 n.Self += v 240 } 241 242 func (t *Tree) InsertStackString(stack []string, v uint64) { 243 n := t.root 244 for j := range stack { 245 n.Total += v 246 n = n.insertString(stack[j]) 247 } 248 // Leaf. 249 n.Total += v 250 n.Self += v 251 } 252 253 func (t *Tree) Iterate(cb func(key []byte, val uint64)) { 254 nodes := []*treeNode{t.root} 255 prefixes := make([][]byte, 1) 256 prefixes[0] = make([]byte, 0) 257 for len(nodes) > 0 { // bfs 258 node := nodes[0] 259 nodes = nodes[1:] 260 261 prefix := prefixes[0] 262 prefixes = prefixes[1:] 263 264 label := append(prefix, semicolon) // byte(';'), 265 l := node.Name 266 label = append(label, l...) // byte(';'), 267 268 cb(label, node.Self) 269 270 nodes = append(node.ChildrenNodes, nodes...) 271 for i := 0; i < len(node.ChildrenNodes); i++ { 272 prefixes = prependBytes(prefixes, label) 273 } 274 } 275 } 276 277 type StackBuilder interface { 278 Push(frame []byte) 279 Pop() // bool 280 Build() (stackID uint64) 281 Reset() 282 } 283 284 func (t *Tree) IterateWithStackBuilder(sb StackBuilder, cb func(stackID uint64, val uint64)) { 285 type indexNode struct { 286 index int 287 node *treeNode 288 } 289 var ss [128]indexNode 290 s := ss[:0] 291 sb.Reset() 292 if t.root.Self != 0 { 293 stackID := sb.Build() 294 cb(stackID, t.root.Self) 295 } 296 for i := 0; i < len(t.root.ChildrenNodes); i++ { 297 { 298 c := t.root.ChildrenNodes[i] 299 s = append(s, indexNode{0, c}) 300 sb.Push(c.Name) 301 if c.Self != 0 { 302 stackID := sb.Build() 303 cb(stackID, c.Self) 304 } 305 } 306 for { 307 if len(s) == 0 { 308 break 309 } 310 h := &s[len(s)-1] 311 nc := len(h.node.ChildrenNodes) 312 if h.index >= nc { 313 s = s[0 : len(s)-1] 314 sb.Pop() 315 continue 316 } 317 c := h.node.ChildrenNodes[h.index] 318 s = append(s, indexNode{0, c}) 319 sb.Push(c.Name) 320 if c.Self != 0 { 321 stackID := sb.Build() 322 cb(stackID, c.Self) 323 } 324 h.index++ 325 } 326 } 327 } 328 329 func (t *Tree) IterateStacks(cb func(name string, self uint64, stack []string)) { 330 nodes := make([]*treeNode, 0, 1024) 331 nodes = append(nodes, t.root) 332 parents := make(map[*treeNode]*treeNode) 333 stack := make([]string, 0, 64) 334 335 for len(nodes) > 0 { 336 node := nodes[0] // todo we need to chop off the last element, to avoid allocations 337 self := node.Self 338 label := node.nameAsStringUnsafe() 339 if self > 0 { 340 current := node 341 stack = stack[:0] 342 for current != nil && current != t.root { 343 stack = append(stack, current.nameAsStringUnsafe()) 344 current = parents[current] 345 } 346 cb(label, self, stack) 347 } 348 nodes = nodes[1:] 349 for _, child := range node.ChildrenNodes { 350 nodes = append(nodes, child) 351 parents[child] = node 352 } 353 } 354 } 355 356 func (n *treeNode) nameAsStringUnsafe() string { 357 if len(n.Name) == 0 { 358 return "" 359 } 360 //return unsafe.String(&n.Name[0], len(n.Name)) 361 res := *(*string)(unsafe.Pointer(&n.Name)) 362 return res 363 } 364 365 func (t *Tree) iterateWithTotal(cb func(total uint64) bool) { 366 nodes := []*treeNode{t.root} 367 i := 0 368 for len(nodes) > 0 { 369 node := nodes[0] 370 nodes = nodes[1:] 371 i++ 372 if cb(node.Total) { 373 nodes = append(node.ChildrenNodes, nodes...) 374 } 375 } 376 } 377 378 func (t *Tree) Scale(s uint64) { 379 nodes := make([]*treeNode, 0, 1024) 380 nodes = append(nodes, t.root) 381 382 for len(nodes) > 0 { 383 node := nodes[len(nodes)-1] 384 nodes = nodes[:len(nodes)-1] 385 386 node.Self *= s 387 node.Total *= s 388 389 nodes = append(nodes, node.ChildrenNodes...) 390 } 391 } 392 func (t *Tree) Samples() uint64 { 393 return t.root.Total 394 } 395 396 func (t *Tree) Clone(r *big.Rat) *Tree { 397 t.RLock() 398 defer t.RUnlock() 399 400 m := uint64(r.Num().Int64()) 401 d := uint64(r.Denom().Int64()) 402 newTrie := &Tree{ 403 root: t.root.clone(m, d), 404 } 405 406 return newTrie 407 } 408 409 func (t *Tree) MarshalJSON() ([]byte, error) { 410 t.RLock() 411 defer t.RUnlock() 412 return json.Marshal(t.root) 413 }