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  }