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