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  }